Please view the tutorial in safari, firefox or internet explorer (chrome’s pdf viewer doesnt load all of the pdf’s in the tutorial).
The following tutorial shows the basics of setting up and interacting with an ArchR Project using a gold-standard downsampled dataset of hematopoietic cells Granja* et al. Nature Biotechnology 2019. This tutorial and all of the accompanying vignettes assume that you are running ArchR locally. Once all of these steps work for you, feel free to set up ArchR to work in a cluster environment. This tutorial does not explain every detail of every step. Please see the Vignettes section for more details on each major analytical step and all of the major features of ArchR.
What is an ArrowFile / ArchRProject?
The base unit of an analytical project in ArchR is called an ArrowFile. Each ArrowFile, stores all of the data associated with an individual sample (i.e. metadata, accessible fragments and data matrices). Here, a sample would be the most detailed unit of analysis desired (for ex. a single replicate of a particular condition). During creation and as additional analyses are performed, ArchR updates and edits each ArrowFile to contain additional layers of information. Then, an ArchRProject allows you to associate these ArrowFiles together into a single analytical framework.
Certain actions can be taken directly on ArrowFiles while other actions are taken on an ArchRProject which in turn updates each associated ArrowFile. Because ArrowFiles are stored as large HDF5-format files, “get-er” functions in ArchR retrieve data by interacting with the ArchRProject.
Getting Set Up
The first thing we do is set up our working directory, load our genome annotations, and set the number of threads we would like to use. Depending on the configuration of your local environment, you may need to modify the number of threads used below in addArchRThreads.
Tidying up our data and creating an ArchRProject
One major source of trouble in single-cell data is the contribution of “doublets” to the analysis. A doublet refers to a single droplet that received a single barcoded bead and more than one nucleus. This causes the reads from more than one cell to appear as a single cell. We remove these computationally and describe this doublet removal process in more depth in the doublet removal vignette.
#Add Infered Doublet Scores to each Arrow File (~2-5 min per sample)
doubScores <- addDoubletScores(ArrowFiles)
#Create ArchRProject
#The outputDirectory here describes where all downstream analyses and plots go.
proj <- ArchRProject(
ArrowFiles = ArrowFiles,
geneAnnotation = geneAnno,
genomeAnnotation = genomeAnno,
outputDirectory = "Heme_Tutorial"
)
#To see information about ArchR Project created simply input
proj
#We can now visualize numeric metadata per grouping with a violin plot now that we have created an ArchR Project.
#For example we will plot TSS / Doublet Enrichment Scores per sample.
plotList <- list()
plotList[[1]] <- plotGroups(ArchRProj = proj,
groupBy = "Sample",
colorBy = "colData",
name = "TSSEnrichment",
)
plotList[[2]] <- plotGroups(ArchRProj = proj,
groupBy = "Sample",
colorBy = "colData",
name = "DoubletEnrichment",
)
plotPDF(plotList = plotList, name = "TSS-Doublet-Enrichment", width = 4, height = 4, ArchRProj = proj, addDOC = FALSE)
#Filter Doublets
#The automatic filtering rate will be based on how many cells are in the sample, if there
#are 5,000 cells ArchR will remove up to 250 (~5%) of the cells. If you believe more cells
#should be excluded change the filterRatio argument apropriately.
proj <- filterDoublets(proj)
Example Doublet Results
Since this was plotted prior to creation of an ArchRProject we go to QualityControl/scATAC_BMMC_R2/scATAC_BMMC_R2-Doublet-Summary.pdf for the plot below.
TSS / Doublet Enrichment
Dimensionality Reduction
At this point, we have an ArchR project that is ready to be used in downstream visualizations and analyses. The first thing we will do is use an iterative latent semantic indexing (LSI) approach to define clusters in our data. Once we have identified clusters in our data, we can plot a UMAP embedding. For more details, see the dimensionality reduction vignette.
#Reduce Dimensions with Iterative LSI (~5-10 minutes)
proj <- addIterativeLSI(
ArchRProj = proj,
useMatrix = "TileMatrix",
reducedDimsOut = "IterativeLSI"
)
#Identify Clusters from Iterative LSI
#By default ArchR uses Seurat's FindClusters function because it is fast/robust producing reasonable clustering.
#The larger the resolution the more clusters will be called. The lower the resolution hte less clusters will be called.
#It is recommended to compare the results from your clusters and your embeddings and find params that best agree across
#both analyses for clarity.
proj <- addClusters(input = proj, reducedDims = "IterativeLSI", resolution = 0.6)
#Compute a UMAP embedding to visualize our tiled accessibility matrix in a 2-d setting.
proj <- addEmbedding(
ArchRProj = proj,
reducedDims = "IterativeLSI",
embedding = "UMAP",
embeddingParams = list(min_dist = 0.4) #see uwot::umap for alternative params
)
#Plot the UMAP Embedding with Metadata Overlayed such as Experimental Sample and Clusters.
#To change plotting aesthetics see ?plotEmbedding parameters.
plotList <- list()
plotList[[1]] <- plotEmbedding(ArchRProj = proj, colorBy = "colData", name = "Sample")
plotList[[2]] <- plotEmbedding(ArchRProj = proj, colorBy = "colData", name = "Clusters", plotParams = list(labelMeans=TRUE))
#Different ArchRPalette "circus"
plotList[[3]] <- plotEmbedding(ArchRProj = proj, colorBy = "colData", name = "Clusters", discreteSet = "circus", plotParams = list(labelMeans=TRUE))
plotPDF(plotList = plotList, name = "UMAP-Samples-Clusters", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
UMAP w/ Clusters
This
plot shows gene experimental samples and clusters described above overlayed onto the UMAP embedding. (Note if you see a blank space below try firefox or safari)
TSNE w/ Clusters
#Compute a TSNE embedding to visualize our tiled accessibility matrix in a 2-d setting.
proj <- addEmbedding(
ArchRProj = proj,
reducedDims = "IterativeLSI",
embedding = "Rtsne",
embeddingParams = list(perplexity = 50)
)
#Plot the TSNE Embedding with Metadata Overlayed such as Experimental Sample and Clusters.
#To change plotting aesthetics see ?plotEmbedding parameters.
plotList <- list()
plotList[[1]] <- plotEmbedding(ArchRProj = proj, colorBy = "colData", embedding = "Rtsne", name = "Sample")
plotList[[2]] <- plotEmbedding(ArchRProj = proj, colorBy = "colData", embedding = "Rtsne", name = "Clusters", plotParams = list(labelMeans=TRUE))
#Different ArchRPalette "circus"
plotList[[3]] <- plotEmbedding(ArchRProj = proj, colorBy = "colData", embedding = "Rtsne", name = "Clusters", discreteSet = "circus", plotParams = list(labelMeans=TRUE))
plotPDF(plotList = plotList, name = "TSNE-Samples-Clusters", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
UMAP w/ Custom ColData
To add your own information for plotting ontop of UMAP embedding we will show an example here.
#Get Cell Names
cellNames <- getCellNames(ArchRProj = proj)
#Get Sample names
sampleNames <- getCellColData(ArchRProj = proj, select = "Sample", drop = TRUE)
#Remove Replicate Name
sampleNames <- gsub("_R1", "", gsub("_R2", "", sampleNames))
#Add Info to cellColData
proj <- addCellColData(ArchRProj = proj, data = sampleNames, cellNames = cellNames, name = "Type")
#Plot the UMAP Embedding with Metadata Overlayed such as Experimental Sample and Clusters.
#To change plotting aesthetics see ?plotEmbedding parameters.
plotList <- list()
plotList[[1]] <- plotEmbedding(ArchRProj = proj, colorBy = "colData", name = "Type", plotParams = list(labelMeans=TRUE))
plotList[[2]] <- plotEmbedding(ArchRProj = proj, colorBy = "colData", name = "Type", discreteSet = "circus", plotParams = list(labelMeans=TRUE))
plotPDF(plotList = plotList, name = "UMAP-Samples-Type", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
Identifying Cluster Cell Types Using Marker Genes
In order to understand which clusters correspond to which cell types, we use a supervised approach based on prior knowledge of the genes that are active in specific cell types. We determine gene activity scores for each putative marker gene based on chromatin accessibility signal in the region surrounding the gene’s promoter. We can then overlay these gene activity scores on our UMAP embedding to visualize the relationship between gene activity and cluster. For more details, see the marker genes vignette.
#Add Imputation Weights for imputing numerical values based on Magic (see van Dijk et. al. 2018).
proj <- addImputeWeights(ArchRProj = proj)
markerGenes <- c(
"CD34", #Early Progenitor
"GATA1", #Erythroid
"PAX5", "MS4A1", #B-Cell Trajectory
"CD14", #Monocytes
"CD3D", "CD8A", "TBX21", "IL7R" #TCells
)
#Plot the UMAP Embedding with Marker Genes Overlayed w/ Imputation
plotList <- list()
plotList[[1]] <- plotEmbedding(ArchRProj = proj, colorBy = "GeneScoreMatrix", name = markerGenes, imputeWeights = getImputeWeights(proj))
plotPDF(plotList = plotList, name = "UMAP-Marker-Gene-Scores-w-Imputation", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
#Plot the UMAP Embedding with Marker Genes Overlayed w/o Imputation
plotList <- list()
plotList[[1]] <- plotEmbedding(ArchRProj = proj, colorBy = "GeneScoreMatrix", name = markerGenes)
plotPDF(plotList = plotList, name = "UMAP-Marker-Gene-Scores-wo-Imputation", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
#Plot Tracks at Marker Genes
plotTracks <- ArchRRegionTrack(ArchRProj = proj, geneSymbol = markerGenes)
plotPDF(plotList = plotTracks, name = "Plot-Tracks-Marker-Genes", width = 6, height = 8, ArchRProj = proj, addDOC = FALSE)
#Identify Marker Gene through Pairwise Test vs Bias-Matched Background
markersGS <- markerFeatures(ArchRProj = proj, useMatrix = "GeneScoreMatrix", groupBy = "Clusters")
heatmapGS <- markerHeatmap(
seMarker = markersGS,
cutOff = "FDR <= 0.01 & Log2FC >= 1",
labelMarkers = markerGenes
)
plotPDF(heatmapGS, name = "GeneScores-Marker-Heatmap", width = 8, height = 12, ArchRProj = proj, addDOC = FALSE)
UMAP GeneScores w/ Imputation
This
plot shows gene activity scores of the marker genes described above overlayed onto the UMAP embedding. The gene scores are imputed using Magic when running addImupteWeights. (Note if you see a blank space below try firefox or safari)
UMAP GeneScores w/o Imputation
This
plot shows gene activity scores of the marker genes described above overlayed onto the UMAP embedding. (Note if you see a blank space below try firefox or safari)
Track-Plots
Marker GeneScores Heatmap
Creating a Reproducible Peak Set
One of the most complicated aspects about ATAC-seq and scATAC-seq analysis is the generation of a reproducible and robust peak set. In ArchR, we use an iterative overlap removal process that we first described in Corces* & Granja* et al. Science 2018. This process is described in detail in the peak calling vignette.
To robustly call peaks, we first merge the sparse single-cell data into pseudo-bulk replicates by aggregating the insertions from many individual cells into a single group. We make multiple pseudo-bulk replicates for each cluster to enable an assessment of peak reproducibility. This process of pseudo-bulk generation is described in detail in the pseudo-bulk generation vignette. We than call peaks using MACS2 and perform our iterative overlap removal. Once we obtain a finalized non-overlapping peak set, we can then collect insertion counts in each peak for each single cell and associate this with the corresponding ArrowFile via the ArchRProject.
#Create Group Coverage Files that can be used for downstream analysis (~5-10 minutes)
proj <- addGroupCoverages(ArchRProj = proj, groupBy = "Clusters")
#Call Reproducible Peaks w/ Macs2 (~5-10 minutes)
proj <- addReproduciblePeakSet(ArchRProj = proj, groupBy = "Clusters")
#Add Peak Matrix
proj <- addPeakMatrix(ArchRProj = proj)
#We can now plot the fraction of reads/insertions for each cell per sample and see how that compares to TSS Enrichment scores.
plotList <- list()
plotList[[1]] <- plotGroups(ArchRProj = proj,
groupBy = "Sample",
colorBy = "colData",
name = "FRIP",
)
plotList[[2]] <- plotGroups(ArchRProj = proj,
groupBy = "Sample",
colorBy = "colData",
name = "TSSEnrichment",
)
plotPDF(plotList = plotList, name = "FRIP-TSS-Enrichment", width = 4, height = 4, ArchRProj = proj, addDOC = FALSE)
Reproducible Peaks per Cluster
FRIP / TSS Enrichment Per Sample
Identifying Marker Peaks
Often times, we are interested to know which peaks are unique to an individual cluster or a small group of clusters. We can do this in an unsupervised fashion in ArchR:
Markers Heatmap
Markers MA/Volcano-Plot
#Marker Peaks for Cluster 6 (Erythroid)
plotList <- list()
plotList[[1]] <- markerPlot(seMarker = markersPeaks, name = "Cluster6", cutOff = "FDR <= 0.1 & abs(Log2FC) >= 1", plotAs = "MA")
plotList[[2]] <- markerPlot(seMarker = markersPeaks, name = "Cluster6", cutOff = "FDR <= 0.1 & abs(Log2FC) >= 1", plotAs = "Volcano")
plotPDF(plotList = plotList, name = "Cluster6-Marker-Peaks", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
Pairwise-Test
#Pairwise Test between Cluster 6 (Erythroid) and Cluster 10 (B-Cells)
testClust6_10 <- markerFeatures(
ArchRProj = proj,
useMatrix = "PeakMatrix",
groupBy = "Clusters",
testMethod = "wilcoxon",
bias = c("TSSEnrichment", "log10(nFrags)"),
useGroups = "Cluster6",
bgdGroups = "Cluster10"
)
#Plot Differential Plot
plotList <- list()
plotList[[1]] <- markerPlot(seMarker = testClust6_10, name = "Cluster6", cutOff = "FDR <= 0.1 & abs(Log2FC) >= 1", plotAs = "MA")
plotList[[2]] <- markerPlot(seMarker = testClust6_10, name = "Cluster6", cutOff = "FDR <= 0.1 & abs(Log2FC) >= 1", plotAs = "Volcano")
plotPDF(plotList = plotList, name = "Cluster6-Cluster10-Marker-Peaks", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
#Add Motif Peak Annotations if not already added!
proj <- addMotifAnnotations(ArchRProj = proj, motifSet = "cisbp", name = "Motif")
#Identify Motif Enrichments
motifsUp <- peakAnnoEnrichment(
seMarker = testClust6_10,
ArchRProj = proj,
peakAnnotation = "Motif",
cutOff = "FDR <= 0.1 & Log2FC >= 0.5"
)
#Create data.frame
df <- data.frame(TF = rownames(motifsUp), mlog10FDR = assay(motifsUp)[,1])
df <- df[order(df$mlog10FDR, decreasing = TRUE),]
df$rank <- seq_len(nrow(df))
#Ggplot
ggUp <- ggplot(df, aes(rank, mlog10FDR)) +
geom_point(size = 1) +
ggrepel::geom_label_repel(
data = df[rev(seq_len(30)), ], aes(x = rank, y = mlog10FDR, label = TF),
size = 1.5,
nudge_x = 2
) + theme_ArchR() + ylab("-log10(FDR) Motif Enrichment") + xlab("Rank Sorted TFs Enriched")
plotPDF(ggUp, name = "Cluster6-Cluster10-Motifs-Up", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
motifsDo <- peakAnnoEnrichment(
seMarker = testClust6_10,
ArchRProj = proj,
peakAnnotation = "Motif",
cutOff = "FDR <= 0.1 & Log2FC <= -0.5"
)
#Create data.frame
df <- data.frame(TF = rownames(motifsDo), mlog10FDR = assay(motifsDo)[,1])
df <- df[order(df$mlog10FDR, decreasing = TRUE),]
df$rank <- seq_len(nrow(df))
#Ggplot
ggDo <- ggplot(df, aes(rank, mlog10FDR)) +
geom_point(size = 1) +
ggrepel::geom_label_repel(
data = df[rev(seq_len(30)), ], aes(x = rank, y = mlog10FDR, label = TF),
size = 1.5,
nudge_x = 2
) + theme_ArchR() + ylab("-log10(FDR) Motif Enrichment") + xlab("Rank Sorted TFs Enriched")
plotPDF(ggDo, name = "Cluster6-Cluster10-Motifs-Down", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
Computing chromVAR Deviations
Using the reproducible peak set that we defined above, we can use ArchR to calculate TF/Annotation deviations on a single-cell basis for transcription factors/annotations in the peaks identified in each cluster. We can then overlay these deviations on on UMAP embedding. This effectively infers differences in TF activity across all single cells and is very useful in identifying regulatory factors governing cell fate.
Motif Deviations
#To access motif need to specify deviations,z : motif_name
#Try getFeatures with MotifMatrix to see available names
getFeatures(proj, select = "PAX5", useMatrix = "MotifMatrix")
#Define the list of motifs to plot
markerMotifs <- c("GATA1_383", "CEBPA_155", "EBF1_67", "IRF4_632", "TBX21_780", "PAX5_709")
#Plot Violins of motif deviations
plotList <- list()
plotList[[1]] <- plotGroups(ArchRProj = proj,
groupBy = "Clusters",
colorBy = "MotifMatrix",
name = paste0("z:",markerMotifs[1]),
imputeWeights = getImputeWeights(proj)
)
plotList[[2]] <- plotGroups(ArchRProj = proj,
groupBy = "Clusters",
colorBy = "MotifMatrix",
name = paste0("z:",markerMotifs[6]),
imputeWeights = getImputeWeights(proj)
)
plotPDF(plotList = plotList, name = "Groups-Marker-MotifDeviations-w-Imputation", width = 4, height = 3, ArchRProj = proj, addDOC = FALSE)
#Plot the UMAP Embedding with chromVAR Deviations Overlayed
plotList <- list()
plotList[[1]] <- plotEmbedding(ArchRProj = proj, colorBy = "colData", name = "Clusters")
plotList[[2]] <- plotEmbedding(ArchRProj = proj, colorBy = "MotifMatrix", name = paste0("z:",markerMotifs), imputeWeights = getImputeWeights(proj))
plotPDF(plotList = plotList, name = "UMAP-Marker-MotifDeviations-w-Imputation", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
Region Deviations
#Add Background Peaks to ArchR Project
proj <- addBgdPeaks(proj)
#Add chromVAR Deviations
proj <- addDeviationsMatrix(ArchRProj = proj, peakAnnotation = "ChIP")
#To access motif need to specify deviations,z : motif_name
#Try getFeatures with MotifMatrix to see available names
getFeatures(proj, select = "PAX5", useMatrix = "ChIPMatrix")
#Define the list of regions to plot
markerRegions <- c("Encode_K562_GATA1", "Encode_GM12878_CEBPB", "Encode_K562_Ebf1", "Encode_K562_Pax5")
#Plot Violins of ChIP-seq deviations
plotList <- list()
plotList[[1]] <- plotGroups(ArchRProj = proj,
groupBy = "Clusters",
colorBy = "ChIPMatrix",
name = paste0("z:",markerRegions[1]),
imputeWeights = getImputeWeights(proj)
)
plotList[[2]] <- plotGroups(ArchRProj = proj,
groupBy = "Clusters",
colorBy = "ChIPMatrix",
name = paste0("z:",markerRegions[4]),
imputeWeights = getImputeWeights(proj)
)
plotPDF(plotList = plotList, name = "Groups-Marker-ChIPDeviations-w-Imputation", width = 4, height = 3, ArchRProj = proj, addDOC = FALSE)
#Plot the UMAP Embedding with chromVAR Deviations Overlayed
plotList <- list()
plotList[[1]] <- plotEmbedding(ArchRProj = proj, colorBy = "colData", name = "Clusters")
plotList[[2]] <- plotEmbedding(ArchRProj = proj, colorBy = "ChIPMatrix", name = paste0("z:",markerRegions), imputeWeights = getImputeWeights(proj))
plotPDF(plotList = plotList, name = "UMAP-Marker-ChIPDeviations-w-Imputation", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
Analyze Trajectories
Myeloid Trajectory
#First we need to create a Trajectory and add it to ArchRProj cellColData
proj <- addTrajectory(ArchRProj = proj, name = "Myeloid", trajectory = c(paste0("Cluster", c(7,2,3,4,5))))
#Additionally we can plot these features on top of the UMAP embedding
plotList <- list()
plotList[[1]] <- plotEmbedding(ArchRProj = proj, colorBy = "colData", name = "Clusters", plotParams = list(labelMeans=TRUE))
plotList[[2]] <- plotTrajectory(proj, trajectory = "Myeloid", colorBy = "colData", name = "Myeloid")
plotList[[3]] <- plotTrajectory(proj, trajectory = "Myeloid", colorBy = "GeneScoreMatrix", name = "CEBPB")
plotList[[4]] <- plotTrajectory(proj, trajectory = "Myeloid", colorBy = "MotifMatrix", name = "z:CEBPB_140")
plotPDF(plotList = plotList, name = "Plot-UMAP-Myeloid-Trajectory", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
#Next we can access variable features across the trajectory and summarize
TrajMyeloidMM <- getTrajectory(ArchRProj = proj, name = "Myeloid", useMatrix = "MotifMatrix", log2Norm = FALSE)
TrajMyeloidGS <- getTrajectory(ArchRProj = proj, name = "Myeloid", useMatrix = "GeneScoreMatrix")
#We can then plot a heatmap for this trajectory to see variable features
plotList <- list()
plotList[[1]] <- trajectoryHeatmap(TrajMyeloidMM)
plotList[[2]] <- trajectoryHeatmap(TrajMyeloidGS)
plotPDF(plotList = plotList, name = "Myeloid-Trajectory-Heatmap", width = 8, height = 12, ArchRProj = proj, addDOC = FALSE)
Lymphoid Trajectory
#First we need to create a Trajectory and add it to ArchRProj cellColData
proj <- addTrajectory(ArchRProj = proj, name = "Lymphoid", trajectory = c(paste0("Cluster", c(7,8,9,10))))
#Additionally we can plot these features on top of the UMAP embedding
plotList <- list()
plotList[[1]] <- plotEmbedding(ArchRProj = proj, colorBy = "colData", name = "Clusters", plotParams = list(labelMeans=TRUE))
plotList[[2]] <- plotTrajectory(proj, trajectory = "Lymphoid", colorBy = "colData", name = "Lymphoid")
plotList[[3]] <- plotTrajectory(proj, trajectory = "Lymphoid", colorBy = "GeneScoreMatrix", name = "PAX5")
plotList[[4]] <- plotTrajectory(proj, trajectory = "Lymphoid", colorBy = "MotifMatrix", name = "z:PAX5_709")
plotPDF(plotList = plotList, name = "Plot-UMAP-Lymphoid-Trajectory", width = 6, height = 6, ArchRProj = proj, addDOC = FALSE)
#Next we can access variable features across the trajectory and summarize
TrajLymphoidMM <- getTrajectory(ArchRProj = proj, name = "Lymphoid", useMatrix = "MotifMatrix", log2Norm = FALSE)
TrajLymphoidGS <- getTrajectory(ArchRProj = proj, name = "Lymphoid", useMatrix = "GeneScoreMatrix")
#We can then plot a heatmap for this trajectory to see variable features
plotList <- list()
plotList[[1]] <- trajectoryHeatmap(TrajLymphoidMM, labelMarkers = "PAX5_709")
plotList[[2]] <- trajectoryHeatmap(TrajLymphoidGS)
plotPDF(plotList = plotList, name = "Lymphoid-Trajectory-Heatmap", width = 8, height = 12, ArchRProj = proj, addDOC = FALSE)
Citation
LS0tCnRpdGxlOiAiR2V0dGluZyBTdGFydGVkIFdpdGggQXJjaFIiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlICMgdGFibGUgb2YgY29udGVudCB0cnVlCiAgICB0b2NfZGVwdGg6IDMgICMgdXB0byB0aHJlZSBkZXB0aHMgb2YgaGVhZGluZ3MgKHNwZWNpZmllZCBieSAjLCAjIyBhbmQgIyMjKQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlICAjIyBpZiB5b3Ugd2FudCBudW1iZXIgc2VjdGlvbnMgYXQgZWFjaCB0YWJsZSBoZWFkZXIKICAgICN0aGVtZTogY29zbW8gICMgbWFueSBvcHRpb25zIGZvciB0aGVtZSwgdGhpcyBvbmUgaXMgbXkgZmF2b3JpdGUuCiAgICBoaWdobGlnaHQ6IHRhbmdvICAjIHNwZWNpZmllcyB0aGUgc3ludGF4IGhpZ2hsaWdodGluZyBzdHlsZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKCmBgYHtyIGltYWdlLCBpbmNsdWRlPUZBTFNFfQp3ZCA8LSAiL1ZvbHVtZXMvSkdfU1NEXzIvRGF0YS9BbmFseXNpcy9UdXRvcmlhbC9IZW1lX1R1dG9yaWFsMyIKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoCiAgYygKICAgICIuLi8uLi9pbWFnZXMvQXJjaFJQcm9qZWN0X1NjaGVtYXRpYy5wbmciLCAKICAgICIuLi8uLi9pbWFnZXMvQXJjaFJfRnVuY3Rpb25TY2hlbWF0aWMucG5nIgogICAgKQogICkKYGBgCgojIyBQbGVhc2UgdmlldyB0aGUgdHV0b3JpYWwgaW4gc2FmYXJpLCBmaXJlZm94IG9yIGludGVybmV0IGV4cGxvcmVyIChjaHJvbWUncyBwZGYgdmlld2VyIGRvZXNudCBsb2FkIGFsbCBvZiB0aGUgcGRmJ3MgaW4gdGhlIHR1dG9yaWFsKS4KClRoZSBmb2xsb3dpbmcgdHV0b3JpYWwgc2hvd3MgdGhlIGJhc2ljcyBvZiBzZXR0aW5nIHVwIGFuZCBpbnRlcmFjdGluZyB3aXRoIGFuIEFyY2hSIFByb2plY3QgdXNpbmcgYSBnb2xkLXN0YW5kYXJkIGRvd25zYW1wbGVkIGRhdGFzZXQgb2YgaGVtYXRvcG9pZXRpYyBjZWxscyBbR3JhbmphKiBldCBhbC4gTmF0dXJlIEJpb3RlY2hub2xvZ3kgMjAxOV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMzE3OTI0MTEpLiBUaGlzIHR1dG9yaWFsIGFuZCBhbGwgb2YgdGhlIGFjY29tcGFueWluZyB2aWduZXR0ZXMgYXNzdW1lIHRoYXQgeW91IGFyZSBydW5uaW5nIEFyY2hSIF9fbG9jYWxseV9fLiBPbmNlIGFsbCBvZiB0aGVzZSBzdGVwcyB3b3JrIGZvciB5b3UsIGZlZWwgZnJlZSB0byBbc2V0IHVwIEFyY2hSIHRvIHdvcmsgaW4gYSBjbHVzdGVyIGVudmlyb25tZW50XShhcnRpY2xlcy9BcnRpY2xlcy9jbHVzdGVyQ29tcHV0aW5nLmh0bWwpLiBUaGlzIHR1dG9yaWFsIGRvZXMgbm90IGV4cGxhaW4gZXZlcnkgZGV0YWlsIG9mIGV2ZXJ5IHN0ZXAuIFBsZWFzZSBzZWUgdGhlIFtWaWduZXR0ZXMgc2VjdGlvbl0oYXJ0aWNsZXMvaW5kZXguaHRtbCkgZm9yIG1vcmUgZGV0YWlscyBvbiBlYWNoIG1ham9yIGFuYWx5dGljYWwgc3RlcCBhbmQgYWxsIG9mIHRoZSBtYWpvciBmZWF0dXJlcyBvZiBBcmNoUi4KCiMgV2hhdCBpcyBhbiBgQXJyb3dGaWxlYCAvIGBBcmNoUlByb2plY3RgPwoKVGhlIGJhc2UgdW5pdCBvZiBhbiBhbmFseXRpY2FsIHByb2plY3QgaW4gQXJjaFIgaXMgY2FsbGVkIGFuIGBBcnJvd0ZpbGVgLiBFYWNoIGBBcnJvd0ZpbGVgLCBzdG9yZXMgYWxsIG9mIHRoZSBkYXRhIGFzc29jaWF0ZWQgd2l0aCBhbiBpbmRpdmlkdWFsIHNhbXBsZSAoaS5lLiBtZXRhZGF0YSwgYWNjZXNzaWJsZSBmcmFnbWVudHMgYW5kIGRhdGEgbWF0cmljZXMpLiBIZXJlLCBhIHNhbXBsZSB3b3VsZCBiZSB0aGUgbW9zdCBkZXRhaWxlZCB1bml0IG9mIGFuYWx5c2lzIGRlc2lyZWQgKGZvciBleC4gYSBzaW5nbGUgcmVwbGljYXRlIG9mIGEgcGFydGljdWxhciBjb25kaXRpb24pLiBEdXJpbmcgY3JlYXRpb24gYW5kIGFzIGFkZGl0aW9uYWwgYW5hbHlzZXMgYXJlIHBlcmZvcm1lZCwgQXJjaFIgdXBkYXRlcyBhbmQgZWRpdHMgZWFjaCBgQXJyb3dGaWxlYCB0byBjb250YWluIGFkZGl0aW9uYWwgbGF5ZXJzIG9mIGluZm9ybWF0aW9uLgpUaGVuLCBhbiBgQXJjaFJQcm9qZWN0YCBhbGxvd3MgeW91IHRvIGFzc29jaWF0ZSB0aGVzZSBgQXJyb3dGaWxlc2AgdG9nZXRoZXIgaW50byBhIHNpbmdsZSBhbmFseXRpY2FsIGZyYW1ld29yay4KCjxjZW50ZXI+CiFbXSguLi8uLi9pbWFnZXMvQXJjaFJQcm9qZWN0X1NjaGVtYXRpYy5wbmcpe3dpZHRoPTcwMHB4fQo8L2NlbnRlcj4KCkNlcnRhaW4gYWN0aW9ucyBjYW4gYmUgdGFrZW4gZGlyZWN0bHkgb24gYEFycm93RmlsZXNgIHdoaWxlIG90aGVyIGFjdGlvbnMgYXJlIHRha2VuIG9uIGFuIGBBcmNoUlByb2plY3RgIHdoaWNoIGluIHR1cm4gdXBkYXRlcyBlYWNoIGFzc29jaWF0ZWQgYEFycm93RmlsZWAuIEJlY2F1c2UgYEFycm93RmlsZXNgIGFyZSBzdG9yZWQgYXMgbGFyZ2UgSERGNS1mb3JtYXQgZmlsZXMsICJnZXQtZXIiIGZ1bmN0aW9ucyBpbiBBcmNoUiByZXRyaWV2ZSBkYXRhIGJ5IGludGVyYWN0aW5nIHdpdGggdGhlIGBBcmNoUlByb2plY3RgLgoKPGNlbnRlcj4KIVtdKC4uLy4uL2ltYWdlcy9BcmNoUl9GdW5jdGlvblNjaGVtYXRpYy5wbmcpe3dpZHRoPTQwMHB4fQo8L2NlbnRlcj4KCiMgR2V0dGluZyBTZXQgVXAKClRoZSBmaXJzdCB0aGluZyB3ZSBkbyBpcyBzZXQgdXAgb3VyIHdvcmtpbmcgZGlyZWN0b3J5LCBsb2FkIG91ciBnZW5vbWUgYW5ub3RhdGlvbnMsIGFuZCBzZXQgdGhlIG51bWJlciBvZiB0aHJlYWRzIHdlIHdvdWxkIGxpa2UgdG8gdXNlLiBEZXBlbmRpbmcgb24gdGhlIGNvbmZpZ3VyYXRpb24gb2YgeW91ciBsb2NhbCBlbnZpcm9ubWVudCwgeW91IG1heSBuZWVkIHRvIG1vZGlmeSB0aGUgbnVtYmVyIG9mIGB0aHJlYWRzYCB1c2VkIGJlbG93IGluIGBhZGRBcmNoUlRocmVhZHNgLgoKYGBge3IgZXZhbD1GQUxTRX0KI0xvYWQgUiBMaWJyYXJpZXMKbGlicmFyeShBcmNoUikKCiNTZXQvQ3JlYXRlIFdvcmtpbmcgRGlyZWN0b3J5IHRvIEZvbGRlciBmb3IgQW5hbHlzaXMKd2QgPC0gIiIKZGlyLmNyZWF0ZSh3ZCwgc2hvd1dhcm5pbmdzID0gRkFMU0UsIHJlY3Vyc2l2ZSA9IFRSVUUpCnNldHdkKHdkKQoKI0xvYWQgR2Vub21lIEFubm90YXRpb25zLiBBdmFpbGFibGUgYW5ub3RhdGlvbnMgYXJlIGZvciBIZzE5LCBIZzM4LCBNbTksIG9yIE1tMTAuIAojKE5vdGUgaWYgeW91IHdhbnQgdG8gYnVpbGQgYSBjdXN0b20gYW5ub3RhdGlvbiBzZWUgY3JlYXRlR2VuZUFubm90YXRpb24gb3IgY3JlYXRlR2Vub21lQW5ub3RhdGlvbikuCmRhdGEoImdlbmVBbm5vSGcxOSIpCmRhdGEoImdlbm9tZUFubm9IZzE5IikKZ2VuZUFubm8gPC0gZ2VuZUFubm9IZzE5Cmdlbm9tZUFubm8gPC0gZ2Vub21lQW5ub0hnMTkKCiNTZXQgRGVmYXVsdCBUaHJlYWRzIGZvciBBcmNoUiBGdW5jdGlvbnMKI0J5IGRlZmF1bHQgQXJjaFIgdXNlcyB0aGUgdG90YWwgbnVtYmVyIG9mIGNvcmVzIGF2YWlsYWJsZSAvIDIuIElmIHdpbmRvd3MgdGhpcyB3aWxsIGJlIHNldCB0byAxLgphZGRBcmNoUlRocmVhZHMoKQpgYGAKCiMgQ3JlYXRpbmcgQXJyb3cgRmlsZXMgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgpGb3IgdGhpcyB0dXRvcmlhbCwgd2Ugd2lsbCBkb3dubG9hZCBhIGNvbGxlY3Rpb24gb2YgZnJhZ21lbnQgZmlsZXMuIEZyYWdtZW50IGZpbGVzIGFyZSBvbmUgb2YgdGhlIGJhc2UgZmlsZSB0eXBlcyBvZiB0aGUgMTB4IEdlbm9taWNzIGFuYWx5dGljYWwgcGxhdGZvcm0gKGFuZCBvdGhlcnMpIGFuZCBjYW4gYmUgZWFzaWx5IGNyZWF0ZWQgZnJvbSBhbnkgYmFtIGZpbGUuIFNlZSBbdGhlIEFyY2hSIGlucHV0IHR5cGVzIHZpZ25ldHRlXShhcnRpY2xlcy9BcnRpY2xlcy9pbnB1dEZpbGVzLmh0bWwpIGZvciBpbmZvcm1hdGlvbiBvbiBtYWtpbmcgeW91ciBvd24gZnJhZ21lbnQgZmlsZXMuIE9uY2Ugd2UgaGF2ZSBvdXIgZnJhZ21lbnQgZmlsZXMsIHdlIHByb3ZpZGUgdGhlaXIgbmFtZXMgYXMgYSBjaGFyYWN0ZXIgdmVjdG9yIHRvIGBjcmVhdGVBcnJvd0ZpbGVzYC4gRHVyaW5nIGNyZWF0aW9uLCBzb21lIGJhc2ljIG1hdHJpY2VzIGFuZCBkYXRhIGlzIGFkZGVkIHRvIGVhY2ggYEFycm93RmlsZWAgaW5jbHVkaW5nIGEgYFRpbGVNYXRyaXhgIGNvbnRhaW5pbmcgaW5zZXJ0aW9uIGNvdW50cyBhY3Jvc3MgZ2Vub21lLXdpZGUgNTAwLWJwIGJpbnMgKHNlZSBgYWRkVGlsZU1hdHJpeGApIGFuZCBhIGBHZW5lU2NvcmVNYXRyaXhgIHRoYXQgaXMgZGV0ZXJtaW5lZCBiYXNlZCBvbiB3ZWlnaHRpbmcgaW5zZXJ0aW9uIGNvdW50cyBpbiB0aWxlcyBuZWFyYnkgYSBnZW5lIHByb21vdGVyIChzZWUgYGFkZEdlbmVTY29yZU1hdHJpeGApLgoKYGBge3IgZXZhbD1GQUxTRX0KI0dldCBUdXRvcmlhbCBEYXRhIH4yLjJHQiBUbyBEb3dubG9hZCAoaWYgZG93bmxvYWRlZCBhbHJlYWR5IEFyY2hSIHdpbGwgYnlwYXNzIGRvd25sb2FkaW5nKS4KaW5wdXRGaWxlcyA8LSBnZXRUdXRvcmlhbERhdGEoIkhlbWF0b3BvaWVzaXMiKQoKI0NyZWF0ZSBBcnJvdyBGaWxlcyAofjEwLTE1IG1pbnV0ZXMpIHcvIGhlbHBmdWwgbWVzc2FnZXMgZGlzcGxheWluZyBwcm9ncmVzcy4KI1RoaXMgc3RlcCB3aWxsIGZvciBlYWNoIHNhbXBsZSA6CiMgMS4gUmVhZCBBY2Nlc3NpYmxlIEZyYWdtZW50cy4KIyAyLiBJZGVudGlmeSBDZWxscyBRQyBJbmZvcm1hdGlvbiAoVFNTIEVucmljaG1lbnQsIE51Y2xlb3NvbWUgaW5mbykuCiMgMy4gRmlsdGVyIENlbGxzIGJhc2VkIG9uIFFDIHBhcmFtZXRlcnMuCiMgNC4gQ3JlYXRlIGEgVGlsZU1hdHJpeCA1MDAtYnAgZ2Vub21lLXdpZGUuCiMgNS4gQ3JlYXRlIGEgR2VuZVNjb3JlTWF0cml4LgpBcnJvd0ZpbGVzIDwtIGNyZWF0ZUFycm93RmlsZXMoCiAgaW5wdXRGaWxlcyA9IGlucHV0RmlsZXMsCiAgc2FtcGxlTmFtZXMgPSBuYW1lcyhpbnB1dEZpbGVzKSwKICBnZW5lQW5ubyA9IGdlbmVBbm5vLAogIGdlbm9tZUFubm8gPSBnZW5vbWVBbm5vCikKYGBgCioqKgojIyBRQyBUU1MgU2NvcmVzIGJ5IFVuaXF1ZSBGcmFnbWVudHMKU2luY2UgdGhpcyB3YXMgcGxvdHRlZCBwcmlvciB0byBjcmVhdGlvbiBvZiBhbiBBcmNoUlByb2plY3Qgd2UgZ28gdG8gUXVhbGl0eUNvbnRyb2wvc2NBVEFDX0JNTUNfUjIvc2NBVEFDX0JNTUNfUjItVFNTX2J5X1VuaXF1ZV9GcmFncy5wZGYgZm9yIHRoZSBwbG90IGJlbG93Lgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL3NjQVRBQ19CTU1DX1IyLVRTU19ieV9VbmlxdWVfRnJhZ3MucGRmKXt3aWR0aD00NTAgaGVpZ2h0PTQ1MH0KPC9jZW50ZXI+CgojIyBRQyBGcmFnbWVudCBTaXplIERpc3RyaWJ1dGlvbgpTaW5jZSB0aGlzIHdhcyBwbG90dGVkIHByaW9yIHRvIGNyZWF0aW9uIG9mIGFuIEFyY2hSUHJvamVjdCB3ZSBnbyB0byBRdWFsaXR5Q29udHJvbC9zY0FUQUNfQk1NQ19SMi9zY0FUQUNfQk1NQ19SMi1GcmFnbWVudF9TaXplX0Rpc3RyaWJ1dGlvbi5wZGYgZm9yIHRoZSBwbG90IGJlbG93Lgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL3NjQVRBQ19CTU1DX1IyLUZyYWdtZW50X1NpemVfRGlzdHJpYnV0aW9uLnBkZil7d2lkdGg9NDUwIGhlaWdodD0zNTB9CjwvY2VudGVyPgoKCiMgVGlkeWluZyB1cCBvdXIgZGF0YSBhbmQgY3JlYXRpbmcgYW4gYEFyY2hSUHJvamVjdGAgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgpPbmUgbWFqb3Igc291cmNlIG9mIHRyb3VibGUgaW4gc2luZ2xlLWNlbGwgZGF0YSBpcyB0aGUgY29udHJpYnV0aW9uIG9mICJkb3VibGV0cyIgdG8gdGhlIGFuYWx5c2lzLiBBIGRvdWJsZXQgcmVmZXJzIHRvIGEgc2luZ2xlIGRyb3BsZXQgdGhhdCByZWNlaXZlZCBhIHNpbmdsZSBiYXJjb2RlZCBiZWFkIGFuZCBtb3JlIHRoYW4gb25lIG51Y2xldXMuIFRoaXMgY2F1c2VzIHRoZSByZWFkcyBmcm9tIG1vcmUgdGhhbiBvbmUgY2VsbCB0byBhcHBlYXIgYXMgYSBzaW5nbGUgY2VsbC4gV2UgcmVtb3ZlIHRoZXNlIGNvbXB1dGF0aW9uYWxseSBhbmQgZGVzY3JpYmUgdGhpcyBkb3VibGV0IHJlbW92YWwgcHJvY2VzcyBpbiBtb3JlIGRlcHRoIGluIHRoZSBbZG91YmxldCByZW1vdmFsIHZpZ25ldHRlXShhcnRpY2xlcy9BcnRpY2xlcy9kb3VibGV0UmVtb3ZhbC5odG1sKS4KCmBgYHtyIGV2YWw9RkFMU0V9CiNBZGQgSW5mZXJlZCBEb3VibGV0IFNjb3JlcyB0byBlYWNoIEFycm93IEZpbGUgKH4yLTUgbWluIHBlciBzYW1wbGUpCmRvdWJTY29yZXMgPC0gYWRkRG91YmxldFNjb3JlcyhBcnJvd0ZpbGVzKQoKI0NyZWF0ZSBBcmNoUlByb2plY3QKI1RoZSBvdXRwdXREaXJlY3RvcnkgaGVyZSBkZXNjcmliZXMgd2hlcmUgYWxsIGRvd25zdHJlYW0gYW5hbHlzZXMgYW5kIHBsb3RzIGdvLgpwcm9qIDwtIEFyY2hSUHJvamVjdCgKICBBcnJvd0ZpbGVzID0gQXJyb3dGaWxlcywgCiAgZ2VuZUFubm90YXRpb24gPSBnZW5lQW5ubywKICBnZW5vbWVBbm5vdGF0aW9uID0gZ2Vub21lQW5ubywKICBvdXRwdXREaXJlY3RvcnkgPSAiSGVtZV9UdXRvcmlhbCIKKQoKI1RvIHNlZSBpbmZvcm1hdGlvbiBhYm91dCBBcmNoUiBQcm9qZWN0IGNyZWF0ZWQgc2ltcGx5IGlucHV0CnByb2oKCiNXZSBjYW4gbm93IHZpc3VhbGl6ZSBudW1lcmljIG1ldGFkYXRhIHBlciBncm91cGluZyB3aXRoIGEgdmlvbGluIHBsb3Qgbm93IHRoYXQgd2UgaGF2ZSBjcmVhdGVkIGFuIEFyY2hSIFByb2plY3QuCiNGb3IgZXhhbXBsZSB3ZSB3aWxsIHBsb3QgVFNTIC8gRG91YmxldCBFbnJpY2htZW50IFNjb3JlcyBwZXIgc2FtcGxlLgpwbG90TGlzdCA8LSBsaXN0KCkKcGxvdExpc3RbWzFdXSA8LSBwbG90R3JvdXBzKEFyY2hSUHJvaiA9IHByb2osIAogIGdyb3VwQnkgPSAiU2FtcGxlIiwgCiAgY29sb3JCeSA9ICJjb2xEYXRhIiwgCiAgbmFtZSA9ICJUU1NFbnJpY2htZW50IiwKKQpwbG90TGlzdFtbMl1dIDwtIHBsb3RHcm91cHMoQXJjaFJQcm9qID0gcHJvaiwgCiAgZ3JvdXBCeSA9ICJTYW1wbGUiLCAKICBjb2xvckJ5ID0gImNvbERhdGEiLCAKICBuYW1lID0gIkRvdWJsZXRFbnJpY2htZW50IiwKKQpwbG90UERGKHBsb3RMaXN0ID0gcGxvdExpc3QsIG5hbWUgPSAiVFNTLURvdWJsZXQtRW5yaWNobWVudCIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gNCwgIEFyY2hSUHJvaiA9IHByb2osIGFkZERPQyA9IEZBTFNFKQoKI0ZpbHRlciBEb3VibGV0cwojVGhlIGF1dG9tYXRpYyBmaWx0ZXJpbmcgcmF0ZSB3aWxsIGJlIGJhc2VkIG9uIGhvdyBtYW55IGNlbGxzIGFyZSBpbiB0aGUgc2FtcGxlLCBpZiB0aGVyZQojYXJlIDUsMDAwIGNlbGxzIEFyY2hSIHdpbGwgcmVtb3ZlIHVwIHRvIDI1MCAofjUlKSBvZiB0aGUgY2VsbHMuIElmIHlvdSBiZWxpZXZlIG1vcmUgY2VsbHMKI3Nob3VsZCBiZSBleGNsdWRlZCBjaGFuZ2UgdGhlIGZpbHRlclJhdGlvIGFyZ3VtZW50IGFwcm9wcmlhdGVseS4KcHJvaiA8LSBmaWx0ZXJEb3VibGV0cyhwcm9qKQpgYGAKKioqCgojIyBFeGFtcGxlIERvdWJsZXQgUmVzdWx0cwpTaW5jZSB0aGlzIHdhcyBwbG90dGVkIHByaW9yIHRvIGNyZWF0aW9uIG9mIGFuIEFyY2hSUHJvamVjdCB3ZSBnbyB0byBRdWFsaXR5Q29udHJvbC9zY0FUQUNfQk1NQ19SMi9zY0FUQUNfQk1NQ19SMi1Eb3VibGV0LVN1bW1hcnkucGRmCmZvciB0aGUgcGxvdCBiZWxvdy48YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvc2NBVEFDX0JNTUNfUjItRG91YmxldC1TdW1tYXJ5LnBkZil7d2lkdGg9NDUwIGhlaWdodD00NTB9CjwvY2VudGVyPgoKIyMgVFNTIC8gRG91YmxldCBFbnJpY2htZW50Cjxici8+PGJyLz4KPGNlbnRlcj4KIVtBbHRdKC4uLy4uL2ltYWdlcy9UdXRvcmlhbC9UU1MtRG91YmxldC1FbnJpY2htZW50LnBkZil7d2lkdGg9NDUwIGhlaWdodD00NTB9CjwvY2VudGVyPgoKIyBEaW1lbnNpb25hbGl0eSBSZWR1Y3Rpb24gey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgpBdCB0aGlzIHBvaW50LCB3ZSBoYXZlIGFuIEFyY2hSIHByb2plY3QgdGhhdCBpcyByZWFkeSB0byBiZSB1c2VkIGluIGRvd25zdHJlYW0gdmlzdWFsaXphdGlvbnMgYW5kIGFuYWx5c2VzLiBUaGUgZmlyc3QgdGhpbmcgd2Ugd2lsbCBkbyBpcyB1c2UgYW4gaXRlcmF0aXZlIGxhdGVudCBzZW1hbnRpYyBpbmRleGluZyAoTFNJKSBhcHByb2FjaCB0byBkZWZpbmUgY2x1c3RlcnMgaW4gb3VyIGRhdGEuIE9uY2Ugd2UgaGF2ZSBpZGVudGlmaWVkIGNsdXN0ZXJzIGluIG91ciBkYXRhLCB3ZSBjYW4gcGxvdCBhIFVNQVAgZW1iZWRkaW5nLiBGb3IgbW9yZSBkZXRhaWxzLCBzZWUgdGhlIFtkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gdmlnbmV0dGVdKGFydGljbGVzL0FydGljbGVzL2RpbVJlZHVjdGlvbi5odG1sKS4KCmBgYHtyIGV2YWw9RkFMU0V9CiNSZWR1Y2UgRGltZW5zaW9ucyB3aXRoIEl0ZXJhdGl2ZSBMU0kgKH41LTEwIG1pbnV0ZXMpCnByb2ogPC0gYWRkSXRlcmF0aXZlTFNJKAogIEFyY2hSUHJvaiA9IHByb2osIAogIHVzZU1hdHJpeCA9ICJUaWxlTWF0cml4IiwgCiAgcmVkdWNlZERpbXNPdXQgPSAiSXRlcmF0aXZlTFNJIgopCgojSWRlbnRpZnkgQ2x1c3RlcnMgZnJvbSBJdGVyYXRpdmUgTFNJCiNCeSBkZWZhdWx0IEFyY2hSIHVzZXMgU2V1cmF0J3MgRmluZENsdXN0ZXJzIGZ1bmN0aW9uIGJlY2F1c2UgaXQgaXMgZmFzdC9yb2J1c3QgcHJvZHVjaW5nIHJlYXNvbmFibGUgY2x1c3RlcmluZy4KI1RoZSBsYXJnZXIgdGhlIHJlc29sdXRpb24gdGhlIG1vcmUgY2x1c3RlcnMgd2lsbCBiZSBjYWxsZWQuIFRoZSBsb3dlciB0aGUgcmVzb2x1dGlvbiBodGUgbGVzcyBjbHVzdGVycyB3aWxsIGJlIGNhbGxlZC4KI0l0IGlzIHJlY29tbWVuZGVkIHRvIGNvbXBhcmUgdGhlIHJlc3VsdHMgZnJvbSB5b3VyIGNsdXN0ZXJzIGFuZCB5b3VyIGVtYmVkZGluZ3MgYW5kIGZpbmQgcGFyYW1zIHRoYXQgYmVzdCBhZ3JlZSBhY3Jvc3MKI2JvdGggYW5hbHlzZXMgZm9yIGNsYXJpdHkuCnByb2ogPC0gYWRkQ2x1c3RlcnMoaW5wdXQgPSBwcm9qLCByZWR1Y2VkRGltcyA9ICJJdGVyYXRpdmVMU0kiLCByZXNvbHV0aW9uID0gMC42KQoKI0NvbXB1dGUgYSBVTUFQIGVtYmVkZGluZyB0byB2aXN1YWxpemUgb3VyIHRpbGVkIGFjY2Vzc2liaWxpdHkgbWF0cml4IGluIGEgMi1kIHNldHRpbmcuCnByb2ogPC0gYWRkRW1iZWRkaW5nKAogIEFyY2hSUHJvaiA9IHByb2osIAogIHJlZHVjZWREaW1zID0gIkl0ZXJhdGl2ZUxTSSIsIAogIGVtYmVkZGluZyA9ICJVTUFQIiwgCiAgZW1iZWRkaW5nUGFyYW1zID0gbGlzdChtaW5fZGlzdCA9IDAuNCkgI3NlZSB1d290Ojp1bWFwIGZvciBhbHRlcm5hdGl2ZSBwYXJhbXMKKQoKI1Bsb3QgdGhlIFVNQVAgRW1iZWRkaW5nIHdpdGggTWV0YWRhdGEgT3ZlcmxheWVkIHN1Y2ggYXMgRXhwZXJpbWVudGFsIFNhbXBsZSBhbmQgQ2x1c3RlcnMuCiNUbyBjaGFuZ2UgcGxvdHRpbmcgYWVzdGhldGljcyBzZWUgP3Bsb3RFbWJlZGRpbmcgcGFyYW1ldGVycy4KcGxvdExpc3QgPC0gbGlzdCgpCnBsb3RMaXN0W1sxXV0gPC0gcGxvdEVtYmVkZGluZyhBcmNoUlByb2ogPSBwcm9qLCBjb2xvckJ5ID0gImNvbERhdGEiLCBuYW1lID0gIlNhbXBsZSIpCnBsb3RMaXN0W1syXV0gPC0gcGxvdEVtYmVkZGluZyhBcmNoUlByb2ogPSBwcm9qLCBjb2xvckJ5ID0gImNvbERhdGEiLCBuYW1lID0gIkNsdXN0ZXJzIiwgcGxvdFBhcmFtcyA9IGxpc3QobGFiZWxNZWFucz1UUlVFKSkKI0RpZmZlcmVudCBBcmNoUlBhbGV0dGUgImNpcmN1cyIKcGxvdExpc3RbWzNdXSA8LSBwbG90RW1iZWRkaW5nKEFyY2hSUHJvaiA9IHByb2osIGNvbG9yQnkgPSAiY29sRGF0YSIsIG5hbWUgPSAiQ2x1c3RlcnMiLCBkaXNjcmV0ZVNldCA9ICJjaXJjdXMiLCBwbG90UGFyYW1zID0gbGlzdChsYWJlbE1lYW5zPVRSVUUpKQpwbG90UERGKHBsb3RMaXN0ID0gcGxvdExpc3QsIG5hbWUgPSAiVU1BUC1TYW1wbGVzLUNsdXN0ZXJzIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA2LCBBcmNoUlByb2ogPSBwcm9qLCBhZGRET0MgPSBGQUxTRSkKYGBgCgoqKioKIyMgVU1BUCB3LyBDbHVzdGVycwpUaGlzIFtwbG90XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvVU1BUC1TYW1wbGVzLUNsdXN0ZXJzLnBkZikgc2hvd3MgZ2VuZSBleHBlcmltZW50YWwgc2FtcGxlcyBhbmQgY2x1c3RlcnMgZGVzY3JpYmVkIGFib3ZlIG92ZXJsYXllZCBvbnRvIHRoZSBVTUFQIGVtYmVkZGluZy4gKE5vdGUgaWYgeW91IHNlZSBhIGJsYW5rIHNwYWNlIGJlbG93IHRyeSBmaXJlZm94IG9yIHNhZmFyaSkKPGJyLz48YnIvPgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL1VNQVAtU2FtcGxlcy1DbHVzdGVycy5wZGYpe3dpZHRoPTQ1MCBoZWlnaHQ9NDUwfQo8L2NlbnRlcj4KCiMjIFRTTkUgdy8gQ2x1c3RlcnMKYGBge3IgZXZhbD1GQUxTRX0KI0NvbXB1dGUgYSBUU05FIGVtYmVkZGluZyB0byB2aXN1YWxpemUgb3VyIHRpbGVkIGFjY2Vzc2liaWxpdHkgbWF0cml4IGluIGEgMi1kIHNldHRpbmcuCnByb2ogPC0gYWRkRW1iZWRkaW5nKAogIEFyY2hSUHJvaiA9IHByb2osIAogIHJlZHVjZWREaW1zID0gIkl0ZXJhdGl2ZUxTSSIsIAogIGVtYmVkZGluZyA9ICJSdHNuZSIsIAogIGVtYmVkZGluZ1BhcmFtcyA9IGxpc3QocGVycGxleGl0eSA9IDUwKQogICkKCiNQbG90IHRoZSBUU05FIEVtYmVkZGluZyB3aXRoIE1ldGFkYXRhIE92ZXJsYXllZCBzdWNoIGFzIEV4cGVyaW1lbnRhbCBTYW1wbGUgYW5kIENsdXN0ZXJzLgojVG8gY2hhbmdlIHBsb3R0aW5nIGFlc3RoZXRpY3Mgc2VlID9wbG90RW1iZWRkaW5nIHBhcmFtZXRlcnMuCnBsb3RMaXN0IDwtIGxpc3QoKQpwbG90TGlzdFtbMV1dIDwtIHBsb3RFbWJlZGRpbmcoQXJjaFJQcm9qID0gcHJvaiwgY29sb3JCeSA9ICJjb2xEYXRhIiwgZW1iZWRkaW5nID0gIlJ0c25lIiwgbmFtZSA9ICJTYW1wbGUiKQpwbG90TGlzdFtbMl1dIDwtIHBsb3RFbWJlZGRpbmcoQXJjaFJQcm9qID0gcHJvaiwgY29sb3JCeSA9ICJjb2xEYXRhIiwgZW1iZWRkaW5nID0gIlJ0c25lIiwgbmFtZSA9ICJDbHVzdGVycyIsIHBsb3RQYXJhbXMgPSBsaXN0KGxhYmVsTWVhbnM9VFJVRSkpCiNEaWZmZXJlbnQgQXJjaFJQYWxldHRlICJjaXJjdXMiCnBsb3RMaXN0W1szXV0gPC0gcGxvdEVtYmVkZGluZyhBcmNoUlByb2ogPSBwcm9qLCBjb2xvckJ5ID0gImNvbERhdGEiLCBlbWJlZGRpbmcgPSAiUnRzbmUiLCBuYW1lID0gIkNsdXN0ZXJzIiwgZGlzY3JldGVTZXQgPSAiY2lyY3VzIiwgcGxvdFBhcmFtcyA9IGxpc3QobGFiZWxNZWFucz1UUlVFKSkKcGxvdFBERihwbG90TGlzdCA9IHBsb3RMaXN0LCBuYW1lID0gIlRTTkUtU2FtcGxlcy1DbHVzdGVycyIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNiwgQXJjaFJQcm9qID0gcHJvaiwgYWRkRE9DID0gRkFMU0UpCmBgYAo8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvVFNORS1TYW1wbGVzLUNsdXN0ZXJzLnBkZil7d2lkdGg9NDUwIGhlaWdodD00NTB9CjwvY2VudGVyPgoKIyMgVU1BUCB3LyBDdXN0b20gQ29sRGF0YQpUbyBhZGQgeW91ciBvd24gaW5mb3JtYXRpb24gZm9yIHBsb3R0aW5nIG9udG9wIG9mIFVNQVAgZW1iZWRkaW5nIHdlIHdpbGwgc2hvdyBhbiBleGFtcGxlIGhlcmUuCgpgYGB7ciBldmFsPUZBTFNFfQoKI0dldCBDZWxsIE5hbWVzCmNlbGxOYW1lcyA8LSBnZXRDZWxsTmFtZXMoQXJjaFJQcm9qID0gcHJvaikKCiNHZXQgU2FtcGxlIG5hbWVzCnNhbXBsZU5hbWVzIDwtIGdldENlbGxDb2xEYXRhKEFyY2hSUHJvaiA9IHByb2osIHNlbGVjdCA9ICJTYW1wbGUiLCBkcm9wID0gVFJVRSkKCiNSZW1vdmUgUmVwbGljYXRlIE5hbWUKc2FtcGxlTmFtZXMgPC0gZ3N1YigiX1IxIiwgIiIsIGdzdWIoIl9SMiIsICIiLCBzYW1wbGVOYW1lcykpCgojQWRkIEluZm8gdG8gY2VsbENvbERhdGEKcHJvaiA8LSBhZGRDZWxsQ29sRGF0YShBcmNoUlByb2ogPSBwcm9qLCBkYXRhID0gc2FtcGxlTmFtZXMsIGNlbGxOYW1lcyA9IGNlbGxOYW1lcywgbmFtZSA9ICJUeXBlIikKCiNQbG90IHRoZSBVTUFQIEVtYmVkZGluZyB3aXRoIE1ldGFkYXRhIE92ZXJsYXllZCBzdWNoIGFzIEV4cGVyaW1lbnRhbCBTYW1wbGUgYW5kIENsdXN0ZXJzLgojVG8gY2hhbmdlIHBsb3R0aW5nIGFlc3RoZXRpY3Mgc2VlID9wbG90RW1iZWRkaW5nIHBhcmFtZXRlcnMuCnBsb3RMaXN0IDwtIGxpc3QoKQpwbG90TGlzdFtbMV1dIDwtIHBsb3RFbWJlZGRpbmcoQXJjaFJQcm9qID0gcHJvaiwgY29sb3JCeSA9ICJjb2xEYXRhIiwgbmFtZSA9ICJUeXBlIiwgcGxvdFBhcmFtcyA9IGxpc3QobGFiZWxNZWFucz1UUlVFKSkKcGxvdExpc3RbWzJdXSA8LSBwbG90RW1iZWRkaW5nKEFyY2hSUHJvaiA9IHByb2osIGNvbG9yQnkgPSAiY29sRGF0YSIsIG5hbWUgPSAiVHlwZSIsIGRpc2NyZXRlU2V0ID0gImNpcmN1cyIsIHBsb3RQYXJhbXMgPSBsaXN0KGxhYmVsTWVhbnM9VFJVRSkpCnBsb3RQREYocGxvdExpc3QgPSBwbG90TGlzdCwgbmFtZSA9ICJVTUFQLVNhbXBsZXMtVHlwZSIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNiwgQXJjaFJQcm9qID0gcHJvaiwgYWRkRE9DID0gRkFMU0UpCmBgYAo8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvVU1BUC1TYW1wbGVzLVR5cGUucGRmKXt3aWR0aD00NTAgaGVpZ2h0PTQ1MH0KPC9jZW50ZXI+CgojIElkZW50aWZ5aW5nIENsdXN0ZXIgQ2VsbCBUeXBlcyBVc2luZyBNYXJrZXIgR2VuZXMgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgpJbiBvcmRlciB0byB1bmRlcnN0YW5kIHdoaWNoIGNsdXN0ZXJzIGNvcnJlc3BvbmQgdG8gd2hpY2ggY2VsbCB0eXBlcywgd2UgdXNlIGEgc3VwZXJ2aXNlZCBhcHByb2FjaCBiYXNlZCBvbiBwcmlvciBrbm93bGVkZ2Ugb2YgdGhlIGdlbmVzIHRoYXQgYXJlIGFjdGl2ZSBpbiBzcGVjaWZpYyBjZWxsIHR5cGVzLiBXZSBkZXRlcm1pbmUgX2dlbmUgYWN0aXZpdHkgc2NvcmVzXyBmb3IgZWFjaCBwdXRhdGl2ZSBtYXJrZXIgZ2VuZSBiYXNlZCBvbiBjaHJvbWF0aW4gYWNjZXNzaWJpbGl0eSBzaWduYWwgaW4gdGhlIHJlZ2lvbiBzdXJyb3VuZGluZyB0aGUgZ2VuZSdzIHByb21vdGVyLiBXZSBjYW4gdGhlbiBvdmVybGF5IHRoZXNlIF9nZW5lIGFjdGl2aXR5IHNjb3Jlc18gb24gb3VyIFVNQVAgZW1iZWRkaW5nIHRvIHZpc3VhbGl6ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gZ2VuZSBhY3Rpdml0eSBhbmQgY2x1c3Rlci4gRm9yIG1vcmUgZGV0YWlscywgc2VlIHRoZSBbbWFya2VyIGdlbmVzIHZpZ25ldHRlXShhcnRpY2xlcy9BcnRpY2xlcy9nZW5lU2NvcmVzLmh0bWwpLgoKYGBge3IgZXZhbD1GQUxTRX0KCiNBZGQgSW1wdXRhdGlvbiBXZWlnaHRzIGZvciBpbXB1dGluZyBudW1lcmljYWwgdmFsdWVzIGJhc2VkIG9uIE1hZ2ljIChzZWUgdmFuIERpamsgZXQuIGFsLiAyMDE4KS4KcHJvaiA8LSBhZGRJbXB1dGVXZWlnaHRzKEFyY2hSUHJvaiA9IHByb2opCgptYXJrZXJHZW5lcyAgPC0gYygKICAgICJDRDM0IiwgI0Vhcmx5IFByb2dlbml0b3IKICAgICJHQVRBMSIsICNFcnl0aHJvaWQKICAgICJQQVg1IiwgIk1TNEExIiwgI0ItQ2VsbCBUcmFqZWN0b3J5CiAgICAiQ0QxNCIsICNNb25vY3l0ZXMKICAgICJDRDNEIiwgIkNEOEEiLCAiVEJYMjEiLCAiSUw3UiIgI1RDZWxscwogICkKCiNQbG90IHRoZSBVTUFQIEVtYmVkZGluZyB3aXRoIE1hcmtlciBHZW5lcyBPdmVybGF5ZWQgdy8gSW1wdXRhdGlvbgpwbG90TGlzdCA8LSBsaXN0KCkKcGxvdExpc3RbWzFdXSA8LSBwbG90RW1iZWRkaW5nKEFyY2hSUHJvaiA9IHByb2osIGNvbG9yQnkgPSAiR2VuZVNjb3JlTWF0cml4IiwgbmFtZSA9IG1hcmtlckdlbmVzLCBpbXB1dGVXZWlnaHRzID0gZ2V0SW1wdXRlV2VpZ2h0cyhwcm9qKSkKcGxvdFBERihwbG90TGlzdCA9IHBsb3RMaXN0LCBuYW1lID0gIlVNQVAtTWFya2VyLUdlbmUtU2NvcmVzLXctSW1wdXRhdGlvbiIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNiwgQXJjaFJQcm9qID0gcHJvaiwgYWRkRE9DID0gRkFMU0UpCgojUGxvdCB0aGUgVU1BUCBFbWJlZGRpbmcgd2l0aCBNYXJrZXIgR2VuZXMgT3ZlcmxheWVkIHcvbyBJbXB1dGF0aW9uCnBsb3RMaXN0IDwtIGxpc3QoKQpwbG90TGlzdFtbMV1dIDwtIHBsb3RFbWJlZGRpbmcoQXJjaFJQcm9qID0gcHJvaiwgY29sb3JCeSA9ICJHZW5lU2NvcmVNYXRyaXgiLCBuYW1lID0gbWFya2VyR2VuZXMpCnBsb3RQREYocGxvdExpc3QgPSBwbG90TGlzdCwgbmFtZSA9ICJVTUFQLU1hcmtlci1HZW5lLVNjb3Jlcy13by1JbXB1dGF0aW9uIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA2LCBBcmNoUlByb2ogPSBwcm9qLCBhZGRET0MgPSBGQUxTRSkKCiNQbG90IFRyYWNrcyBhdCBNYXJrZXIgR2VuZXMKcGxvdFRyYWNrcyA8LSBBcmNoUlJlZ2lvblRyYWNrKEFyY2hSUHJvaiA9IHByb2osIGdlbmVTeW1ib2wgPSBtYXJrZXJHZW5lcykKcGxvdFBERihwbG90TGlzdCA9IHBsb3RUcmFja3MsIG5hbWUgPSAiUGxvdC1UcmFja3MtTWFya2VyLUdlbmVzIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA4LCBBcmNoUlByb2ogPSBwcm9qLCBhZGRET0MgPSBGQUxTRSkKCiNJZGVudGlmeSBNYXJrZXIgR2VuZSB0aHJvdWdoIFBhaXJ3aXNlIFRlc3QgdnMgQmlhcy1NYXRjaGVkIEJhY2tncm91bmQgCm1hcmtlcnNHUyA8LSBtYXJrZXJGZWF0dXJlcyhBcmNoUlByb2ogPSBwcm9qLCB1c2VNYXRyaXggPSAiR2VuZVNjb3JlTWF0cml4IiwgZ3JvdXBCeSA9ICJDbHVzdGVycyIpCmhlYXRtYXBHUyA8LSBtYXJrZXJIZWF0bWFwKAogIHNlTWFya2VyID0gbWFya2Vyc0dTLCAKICBjdXRPZmYgPSAiRkRSIDw9IDAuMDEgJiBMb2cyRkMgPj0gMSIsIAogIGxhYmVsTWFya2VycyA9IG1hcmtlckdlbmVzCikKcGxvdFBERihoZWF0bWFwR1MsIG5hbWUgPSAiR2VuZVNjb3Jlcy1NYXJrZXItSGVhdG1hcCIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gMTIsIEFyY2hSUHJvaiA9IHByb2osIGFkZERPQyA9IEZBTFNFKQpgYGAKKioqCgojIyBVTUFQIEdlbmVTY29yZXMgdy8gSW1wdXRhdGlvbgpUaGlzIFtwbG90XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvVU1BUC1NYXJrZXItR2VuZS1TY29yZXMtdy1JbXB1dGF0aW9uLnBkZikgc2hvd3MgZ2VuZSBhY3Rpdml0eSBzY29yZXMgb2YgdGhlIG1hcmtlciBnZW5lcyBkZXNjcmliZWQgYWJvdmUgb3ZlcmxheWVkIG9udG8gdGhlIFVNQVAgZW1iZWRkaW5nLiBUaGUgZ2VuZSBzY29yZXMgYXJlIGltcHV0ZWQgdXNpbmcgTWFnaWMgd2hlbiBydW5uaW5nIGFkZEltdXB0ZVdlaWdodHMuIChOb3RlIGlmIHlvdSBzZWUgYSBibGFuayBzcGFjZSBiZWxvdyB0cnkgZmlyZWZveCBvciBzYWZhcmkpCjxici8+PGJyLz4KPGNlbnRlcj4KIVtBbHRdKC4uLy4uL2ltYWdlcy9UdXRvcmlhbC9VTUFQLU1hcmtlci1HZW5lLVNjb3Jlcy13LUltcHV0YXRpb24ucGRmKXt3aWR0aD00NTAgaGVpZ2h0PTQ1MH0KPC9jZW50ZXI+CgojIyBVTUFQIEdlbmVTY29yZXMgdy9vIEltcHV0YXRpb24KVGhpcyBbcGxvdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL1VNQVAtTWFya2VyLUdlbmUtU2NvcmVzLXdvLUltcHV0YXRpb24ucGRmKSBzaG93cyBnZW5lIGFjdGl2aXR5IHNjb3JlcyBvZiB0aGUgbWFya2VyIGdlbmVzIGRlc2NyaWJlZCBhYm92ZSBvdmVybGF5ZWQgb250byB0aGUgVU1BUCBlbWJlZGRpbmcuIChOb3RlIGlmIHlvdSBzZWUgYSBibGFuayBzcGFjZSBiZWxvdyB0cnkgZmlyZWZveCBvciBzYWZhcmkpCjxici8+PGJyLz4KPGNlbnRlcj4KIVtBbHRdKC4uLy4uL2ltYWdlcy9UdXRvcmlhbC9VTUFQLU1hcmtlci1HZW5lLVNjb3Jlcy13by1JbXB1dGF0aW9uLnBkZil7d2lkdGg9NDUwIGhlaWdodD00NTB9CjwvY2VudGVyPgoKIyMgVHJhY2stUGxvdHMKPGJyLz48YnIvPgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL1Bsb3QtVHJhY2tzLU1hcmtlci1HZW5lcy5wZGYpe3dpZHRoPTQ1MCBoZWlnaHQ9NjAwfQo8L2NlbnRlcj4KCiMjIE1hcmtlciBHZW5lU2NvcmVzIEhlYXRtYXAKPGJyLz48YnIvPgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL0dlbmVTY29yZXMtTWFya2VyLUhlYXRtYXAucGRmKXt3aWR0aD00NTAgaGVpZ2h0PTYwMH0KPC9jZW50ZXI+CgojIENyZWF0aW5nIGEgUmVwcm9kdWNpYmxlIFBlYWsgU2V0IHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQoKT25lIG9mIHRoZSBtb3N0IGNvbXBsaWNhdGVkIGFzcGVjdHMgYWJvdXQgQVRBQy1zZXEgYW5kIHNjQVRBQy1zZXEgYW5hbHlzaXMgaXMgdGhlIGdlbmVyYXRpb24gb2YgYSByZXByb2R1Y2libGUgYW5kIHJvYnVzdCBwZWFrIHNldC4gSW4gQXJjaFIsIHdlIHVzZSBhbiBpdGVyYXRpdmUgb3ZlcmxhcCByZW1vdmFsIHByb2Nlc3MgdGhhdCB3ZSBmaXJzdCBkZXNjcmliZWQgaW4gW0NvcmNlcyogJiBHcmFuamEqIGV0IGFsLiBTY2llbmNlIDIwMThdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzMwMzYxMzQxKS4gVGhpcyBwcm9jZXNzIGlzIGRlc2NyaWJlZCBpbiBkZXRhaWwgaW4gdGhlIFtwZWFrIGNhbGxpbmcgdmlnbmV0dGVdKGFydGljbGVzL0FydGljbGVzL3BlYWtDYWxsaW5nLmh0bWwpLgoKVG8gcm9idXN0bHkgY2FsbCBwZWFrcywgd2UgZmlyc3QgbWVyZ2UgdGhlIHNwYXJzZSBzaW5nbGUtY2VsbCBkYXRhIGludG8gcHNldWRvLWJ1bGsgcmVwbGljYXRlcyBieSBhZ2dyZWdhdGluZyB0aGUgaW5zZXJ0aW9ucyBmcm9tIG1hbnkgaW5kaXZpZHVhbCBjZWxscyBpbnRvIGEgc2luZ2xlIGdyb3VwLiBXZSBtYWtlIG11bHRpcGxlIHBzZXVkby1idWxrIHJlcGxpY2F0ZXMgZm9yIGVhY2ggY2x1c3RlciB0byBlbmFibGUgYW4gYXNzZXNzbWVudCBvZiBwZWFrIHJlcHJvZHVjaWJpbGl0eS4gVGhpcyBwcm9jZXNzIG9mIHBzZXVkby1idWxrIGdlbmVyYXRpb24gaXMgZGVzY3JpYmVkIGluIGRldGFpbCBpbiB0aGUgW3BzZXVkby1idWxrIGdlbmVyYXRpb24gdmlnbmV0dGVdKGFydGljbGVzL0FydGljbGVzL3BzZXVkb2J1bGtHZW5lcmF0aW9uLmh0bWwpLiBXZSB0aGFuIGNhbGwgcGVha3MgdXNpbmcgW01BQ1MyXShodHRwczovL2dpdGh1Yi5jb20vdGFvbGl1L01BQ1MpIGFuZCBwZXJmb3JtIG91ciBpdGVyYXRpdmUgb3ZlcmxhcCByZW1vdmFsLiBPbmNlIHdlIG9idGFpbiBhIGZpbmFsaXplZCBub24tb3ZlcmxhcHBpbmcgcGVhayBzZXQsIHdlIGNhbiB0aGVuIGNvbGxlY3QgaW5zZXJ0aW9uIGNvdW50cyBpbiBlYWNoIHBlYWsgZm9yIGVhY2ggc2luZ2xlIGNlbGwgYW5kIGFzc29jaWF0ZSB0aGlzIHdpdGggdGhlIGNvcnJlc3BvbmRpbmcgYEFycm93RmlsZWAgdmlhIHRoZSBgQXJjaFJQcm9qZWN0YC4KCmBgYHtyIGV2YWw9RkFMU0V9CiNDcmVhdGUgR3JvdXAgQ292ZXJhZ2UgRmlsZXMgdGhhdCBjYW4gYmUgdXNlZCBmb3IgZG93bnN0cmVhbSBhbmFseXNpcyAofjUtMTAgbWludXRlcykKcHJvaiA8LSBhZGRHcm91cENvdmVyYWdlcyhBcmNoUlByb2ogPSBwcm9qLCBncm91cEJ5ID0gIkNsdXN0ZXJzIikKCiNDYWxsIFJlcHJvZHVjaWJsZSBQZWFrcyB3LyBNYWNzMiAofjUtMTAgbWludXRlcykKcHJvaiA8LSBhZGRSZXByb2R1Y2libGVQZWFrU2V0KEFyY2hSUHJvaiA9IHByb2osIGdyb3VwQnkgPSAiQ2x1c3RlcnMiKQoKI0FkZCBQZWFrIE1hdHJpeApwcm9qIDwtIGFkZFBlYWtNYXRyaXgoQXJjaFJQcm9qID0gcHJvaikKCiNXZSBjYW4gbm93IHBsb3QgdGhlIGZyYWN0aW9uIG9mIHJlYWRzL2luc2VydGlvbnMgZm9yIGVhY2ggY2VsbCBwZXIgc2FtcGxlIGFuZCBzZWUgaG93IHRoYXQgY29tcGFyZXMgdG8gVFNTIEVucmljaG1lbnQgc2NvcmVzLgpwbG90TGlzdCA8LSBsaXN0KCkKcGxvdExpc3RbWzFdXSA8LSBwbG90R3JvdXBzKEFyY2hSUHJvaiA9IHByb2osIAogIGdyb3VwQnkgPSAiU2FtcGxlIiwgCiAgY29sb3JCeSA9ICJjb2xEYXRhIiwgCiAgbmFtZSA9ICJGUklQIiwKKQpwbG90TGlzdFtbMl1dIDwtIHBsb3RHcm91cHMoQXJjaFJQcm9qID0gcHJvaiwgCiAgZ3JvdXBCeSA9ICJTYW1wbGUiLCAKICBjb2xvckJ5ID0gImNvbERhdGEiLCAKICBuYW1lID0gIlRTU0VucmljaG1lbnQiLAopCnBsb3RQREYocGxvdExpc3QgPSBwbG90TGlzdCwgbmFtZSA9ICJGUklQLVRTUy1FbnJpY2htZW50Iiwgd2lkdGggPSA0LCBoZWlnaHQgPSA0LCAgQXJjaFJQcm9qID0gcHJvaiwgYWRkRE9DID0gRkFMU0UpCmBgYAojIyBSZXByb2R1Y2libGUgUGVha3MgcGVyIENsdXN0ZXIKPGJyLz48YnIvPgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL1BlYWstQ2FsbC1TdW1tYXJ5LnBkZil7d2lkdGg9NjAwIGhlaWdodD00MDB9CjwvY2VudGVyPgoKIyMgRlJJUCAvIFRTUyBFbnJpY2htZW50IFBlciBTYW1wbGUKPGJyLz48YnIvPgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL0ZSSVAtVFNTLUVucmljaG1lbnQucGRmKXt3aWR0aD00NTAgaGVpZ2h0PTQ1MH0KPC9jZW50ZXI+CgoKIyBJZGVudGlmeWluZyBNYXJrZXIgUGVha3Mgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgpPZnRlbiB0aW1lcywgd2UgYXJlIGludGVyZXN0ZWQgdG8ga25vdyB3aGljaCBwZWFrcyBhcmUgdW5pcXVlIHRvIGFuIGluZGl2aWR1YWwgY2x1c3RlciBvciBhIHNtYWxsIGdyb3VwIG9mIGNsdXN0ZXJzLiBXZSBjYW4gZG8gdGhpcyBpbiBhbiB1bnN1cGVydmlzZWQgZmFzaGlvbiBpbiBBcmNoUjoKCmBgYHtyIGV2YWw9RkFMU0V9CiNJZGVudGlmeSBNYXJrZXIgUGVha3MKbWFya2Vyc1BlYWtzIDwtIG1hcmtlckZlYXR1cmVzKEFyY2hSUHJvaiA9IHByb2osIHVzZU1hdHJpeCA9ICJQZWFrTWF0cml4IiwgZ3JvdXBCeSA9ICJDbHVzdGVycyIpCgojVmlzdWFsaXplIE1hcmtlcnMgYXMgYSBoZWF0bWFwCmhlYXRtYXBQZWFrcyA8LSBtYXJrZXJIZWF0bWFwKAogIHNlTWFya2VyID0gbWFya2Vyc1BlYWtzLCAKICBjdXRPZmYgPSAiRkRSIDw9IDAuMSAmIExvZzJGQyA+PSAxIgopCnBsb3RQREYoaGVhdG1hcFBlYWtzLCBuYW1lID0gIlBlYWstTWFya2VyLUhlYXRtYXAiLCB3aWR0aCA9IDgsIGhlaWdodCA9IDEyLCBBcmNoUlByb2ogPSBwcm9qLCBhZGRET0MgPSBGQUxTRSkKYGBgCgojIyBNYXJrZXJzIEhlYXRtYXAKPGJyLz48YnIvPgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL1BlYWstTWFya2VyLUhlYXRtYXAucGRmKXt3aWR0aD00NTAgaGVpZ2h0PTYwMH0KPC9jZW50ZXI+CgojIyBNYXJrZXJzIE1BL1ZvbGNhbm8tUGxvdApgYGB7ciBldmFsPUZBTFNFfQojTWFya2VyIFBlYWtzIGZvciBDbHVzdGVyIDYgKEVyeXRocm9pZCkKcGxvdExpc3QgPC0gbGlzdCgpCnBsb3RMaXN0W1sxXV0gPC0gbWFya2VyUGxvdChzZU1hcmtlciA9IG1hcmtlcnNQZWFrcywgbmFtZSA9ICJDbHVzdGVyNiIsIGN1dE9mZiA9ICJGRFIgPD0gMC4xICYgYWJzKExvZzJGQykgPj0gMSIsIHBsb3RBcyA9ICJNQSIpCnBsb3RMaXN0W1syXV0gPC0gbWFya2VyUGxvdChzZU1hcmtlciA9IG1hcmtlcnNQZWFrcywgbmFtZSA9ICJDbHVzdGVyNiIsIGN1dE9mZiA9ICJGRFIgPD0gMC4xICYgYWJzKExvZzJGQykgPj0gMSIsIHBsb3RBcyA9ICJWb2xjYW5vIikKcGxvdFBERihwbG90TGlzdCA9IHBsb3RMaXN0LCBuYW1lID0gIkNsdXN0ZXI2LU1hcmtlci1QZWFrcyIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNiwgQXJjaFJQcm9qID0gcHJvaiwgYWRkRE9DID0gRkFMU0UpCmBgYAo8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvQ2x1c3RlcjYtTWFya2VyLVBlYWtzLnBkZil7d2lkdGg9NDUwIGhlaWdodD00NTB9CjwvY2VudGVyPgoKIyMgUGFpcndpc2UtVGVzdApgYGB7ciBldmFsPUZBTFNFfQoKI1BhaXJ3aXNlIFRlc3QgYmV0d2VlbiBDbHVzdGVyIDYgKEVyeXRocm9pZCkgYW5kIENsdXN0ZXIgMTAgKEItQ2VsbHMpCnRlc3RDbHVzdDZfMTAgPC0gbWFya2VyRmVhdHVyZXMoCiAgQXJjaFJQcm9qID0gcHJvaiwgCiAgdXNlTWF0cml4ID0gIlBlYWtNYXRyaXgiLAogIGdyb3VwQnkgPSAiQ2x1c3RlcnMiLAogIHRlc3RNZXRob2QgPSAid2lsY294b24iLAogIGJpYXMgPSBjKCJUU1NFbnJpY2htZW50IiwgImxvZzEwKG5GcmFncykiKSwKICB1c2VHcm91cHMgPSAiQ2x1c3RlcjYiLAogIGJnZEdyb3VwcyA9ICJDbHVzdGVyMTAiCikKCiNQbG90IERpZmZlcmVudGlhbCBQbG90CnBsb3RMaXN0IDwtIGxpc3QoKQpwbG90TGlzdFtbMV1dIDwtIG1hcmtlclBsb3Qoc2VNYXJrZXIgPSB0ZXN0Q2x1c3Q2XzEwLCBuYW1lID0gIkNsdXN0ZXI2IiwgY3V0T2ZmID0gIkZEUiA8PSAwLjEgJiBhYnMoTG9nMkZDKSA+PSAxIiwgcGxvdEFzID0gIk1BIikKcGxvdExpc3RbWzJdXSA8LSBtYXJrZXJQbG90KHNlTWFya2VyID0gdGVzdENsdXN0Nl8xMCwgbmFtZSA9ICJDbHVzdGVyNiIsIGN1dE9mZiA9ICJGRFIgPD0gMC4xICYgYWJzKExvZzJGQykgPj0gMSIsIHBsb3RBcyA9ICJWb2xjYW5vIikKcGxvdFBERihwbG90TGlzdCA9IHBsb3RMaXN0LCBuYW1lID0gIkNsdXN0ZXI2LUNsdXN0ZXIxMC1NYXJrZXItUGVha3MiLCB3aWR0aCA9IDYsIGhlaWdodCA9IDYsIEFyY2hSUHJvaiA9IHByb2osIGFkZERPQyA9IEZBTFNFKQoKYGBgCjxici8+PGJyLz4KPGNlbnRlcj4KIVtBbHRdKC4uLy4uL2ltYWdlcy9UdXRvcmlhbC9DbHVzdGVyNi1DbHVzdGVyMTAtTWFya2VyLVBlYWtzLnBkZil7d2lkdGg9NDUwIGhlaWdodD00NTB9CjwvY2VudGVyPgoKYGBge3IgZXZhbD1GQUxTRX0KI0FkZCBNb3RpZiBQZWFrIEFubm90YXRpb25zIGlmIG5vdCBhbHJlYWR5IGFkZGVkIQpwcm9qIDwtIGFkZE1vdGlmQW5ub3RhdGlvbnMoQXJjaFJQcm9qID0gcHJvaiwgbW90aWZTZXQgPSAiY2lzYnAiLCBuYW1lID0gIk1vdGlmIikKCiNJZGVudGlmeSBNb3RpZiBFbnJpY2htZW50cwptb3RpZnNVcCA8LSBwZWFrQW5ub0VucmljaG1lbnQoCiAgICBzZU1hcmtlciA9IHRlc3RDbHVzdDZfMTAsCiAgICBBcmNoUlByb2ogPSBwcm9qLAogICAgcGVha0Fubm90YXRpb24gPSAiTW90aWYiLAogICAgY3V0T2ZmID0gIkZEUiA8PSAwLjEgJiBMb2cyRkMgPj0gMC41IgogICkKCiNDcmVhdGUgZGF0YS5mcmFtZQpkZiA8LSBkYXRhLmZyYW1lKFRGID0gcm93bmFtZXMobW90aWZzVXApLCBtbG9nMTBGRFIgPSBhc3NheShtb3RpZnNVcClbLDFdKQpkZiA8LSBkZltvcmRlcihkZiRtbG9nMTBGRFIsIGRlY3JlYXNpbmcgPSBUUlVFKSxdCmRmJHJhbmsgPC0gc2VxX2xlbihucm93KGRmKSkKCiNHZ3Bsb3QKZ2dVcCA8LSBnZ3Bsb3QoZGYsIGFlcyhyYW5rLCBtbG9nMTBGRFIpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDEpICsKICBnZ3JlcGVsOjpnZW9tX2xhYmVsX3JlcGVsKAogICAgICAgIGRhdGEgPSBkZltyZXYoc2VxX2xlbigzMCkpLCBdLCBhZXMoeCA9IHJhbmssIHkgPSBtbG9nMTBGRFIsIGxhYmVsID0gVEYpLCAKICAgICAgICBzaXplID0gMS41LAogICAgICAgIG51ZGdlX3ggPSAyCiAgKSArIHRoZW1lX0FyY2hSKCkgKyB5bGFiKCItbG9nMTAoRkRSKSBNb3RpZiBFbnJpY2htZW50IikgKyB4bGFiKCJSYW5rIFNvcnRlZCBURnMgRW5yaWNoZWQiKQpwbG90UERGKGdnVXAsIG5hbWUgPSAiQ2x1c3RlcjYtQ2x1c3RlcjEwLU1vdGlmcy1VcCIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNiwgQXJjaFJQcm9qID0gcHJvaiwgYWRkRE9DID0gRkFMU0UpCmBgYAo8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvQ2x1c3RlcjYtQ2x1c3RlcjEwLU1vdGlmcy1VcC5wZGYpe3dpZHRoPTQ1MCBoZWlnaHQ9NDUwfQo8L2NlbnRlcj4KCmBgYHtyIGV2YWw9RkFMU0V9Cm1vdGlmc0RvIDwtIHBlYWtBbm5vRW5yaWNobWVudCgKICAgIHNlTWFya2VyID0gdGVzdENsdXN0Nl8xMCwKICAgIEFyY2hSUHJvaiA9IHByb2osCiAgICBwZWFrQW5ub3RhdGlvbiA9ICJNb3RpZiIsCiAgICBjdXRPZmYgPSAiRkRSIDw9IDAuMSAmIExvZzJGQyA8PSAtMC41IgogICkKCiNDcmVhdGUgZGF0YS5mcmFtZQpkZiA8LSBkYXRhLmZyYW1lKFRGID0gcm93bmFtZXMobW90aWZzRG8pLCBtbG9nMTBGRFIgPSBhc3NheShtb3RpZnNEbylbLDFdKQpkZiA8LSBkZltvcmRlcihkZiRtbG9nMTBGRFIsIGRlY3JlYXNpbmcgPSBUUlVFKSxdCmRmJHJhbmsgPC0gc2VxX2xlbihucm93KGRmKSkKCiNHZ3Bsb3QKZ2dEbyA8LSBnZ3Bsb3QoZGYsIGFlcyhyYW5rLCBtbG9nMTBGRFIpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDEpICsKICBnZ3JlcGVsOjpnZW9tX2xhYmVsX3JlcGVsKAogICAgICAgIGRhdGEgPSBkZltyZXYoc2VxX2xlbigzMCkpLCBdLCBhZXMoeCA9IHJhbmssIHkgPSBtbG9nMTBGRFIsIGxhYmVsID0gVEYpLCAKICAgICAgICBzaXplID0gMS41LAogICAgICAgIG51ZGdlX3ggPSAyCiAgKSArIHRoZW1lX0FyY2hSKCkgKyB5bGFiKCItbG9nMTAoRkRSKSBNb3RpZiBFbnJpY2htZW50IikgKyB4bGFiKCJSYW5rIFNvcnRlZCBURnMgRW5yaWNoZWQiKQpwbG90UERGKGdnRG8sIG5hbWUgPSAiQ2x1c3RlcjYtQ2x1c3RlcjEwLU1vdGlmcy1Eb3duIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA2LCBBcmNoUlByb2ogPSBwcm9qLCBhZGRET0MgPSBGQUxTRSkKCmBgYAo8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvQ2x1c3RlcjYtQ2x1c3RlcjEwLU1vdGlmcy1Eb3duLnBkZil7d2lkdGg9NDUwIGhlaWdodD00NTB9CjwvY2VudGVyPgoKIyBQZXJmb3JtaW5nIFBlYWsgQW5ub3RhdGlvbiBFbnJpY2htZW50cyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCmBgYHtyIGV2YWw9RkFMU0V9CiNNb3RpZiBTZWFyY2ggaW4gUGVhayBTZXQgYW5kIGFkZCB0byBQZWFrIEFubm90YXRpb25zCnByb2ogPC0gYWRkTW90aWZBbm5vdGF0aW9ucyhBcmNoUlByb2ogPSBwcm9qLCBtb3RpZlNldCA9ICJjaXNicCIsIG5hbWUgPSAiTW90aWYiKQoKI0lkZW50aWZ5IE1vdGlmIEVucmljaG1lbnRzCmVucmljaE1vdGlmcyA8LSBwZWFrQW5ub0VucmljaG1lbnQoCiAgICBzZU1hcmtlciA9IG1hcmtlcnNQZWFrcywKICAgIEFyY2hSUHJvaiA9IHByb2osCiAgICBwZWFrQW5ub3RhdGlvbiA9ICJNb3RpZiIsCiAgICBjdXRPZmYgPSAiRkRSIDw9IDAuMSAmIExvZzJGQyA+PSAwLjUiCiAgKQpoZWF0bWFwRU0gPC0gZW5yaWNoSGVhdG1hcChlbnJpY2hNb3RpZnMsIG4gPSAxMCkKcGxvdFBERihoZWF0bWFwRU0sIG5hbWUgPSAiTW90aWZzLUVucmljaC1IZWF0bWFwIiwgd2lkdGggPSA4LCBoZWlnaHQgPSAxMiwgQXJjaFJQcm9qID0gcHJvaiwgYWRkRE9DID0gRkFMU0UpCgojQ3VzdG9tIFBlYWsgQW5ub3RhdGlvbnMKRW5jb2RlUGVha3MgPC0gYygKICBFbmNvZGVfSzU2Ml9HQVRBMSA9ICJodHRwczovL3d3dy5lbmNvZGVwcm9qZWN0Lm9yZy9maWxlcy9FTkNGRjYzMk5RSS9AQGRvd25sb2FkL0VOQ0ZGNjMyTlFJLmJlZC5neiIsCiAgRW5jb2RlX0dNMTI4NzhfQ0VCUEIgPSAiaHR0cHM6Ly93d3cuZW5jb2RlcHJvamVjdC5vcmcvZmlsZXMvRU5DRkY3NjFNR0ovQEBkb3dubG9hZC9FTkNGRjc2MU1HSi5iZWQuZ3oiLAogIEVuY29kZV9LNTYyX0ViZjEgPSAiaHR0cHM6Ly93d3cuZW5jb2RlcHJvamVjdC5vcmcvZmlsZXMvRU5DRkY4NjhWU1kvQEBkb3dubG9hZC9FTkNGRjg2OFZTWS5iZWQuZ3oiLAogIEVuY29kZV9LNTYyX1BheDUgPSAiaHR0cHM6Ly93d3cuZW5jb2RlcHJvamVjdC5vcmcvZmlsZXMvRU5DRkYzMzlLVU8vQEBkb3dubG9hZC9FTkNGRjMzOUtVTy5iZWQuZ3oiCikKcHJvaiA8LSBhZGRQZWFrQW5ub3RhdGlvbnMoQXJjaFJQcm9qID0gcHJvaiwgcmVnaW9ucyA9IEVuY29kZVBlYWtzLCBuYW1lID0gIkNoSVAiKQoKI0lkZW50aWZ5IENoSVAgRW5yaWNobWVudHMKZW5yaWNoUmVnaW9ucyA8LSBwZWFrQW5ub0VucmljaG1lbnQoCiAgICBzZU1hcmtlciA9IG1hcmtlcnNQZWFrcywKICAgIEFyY2hSUHJvaiA9IHByb2osCiAgICBwZWFrQW5ub3RhdGlvbiA9ICJDaElQIiwKICAgIGN1dE9mZiA9ICJGRFIgPD0gMC4xICYgTG9nMkZDID49IDAuNSIKICApCmhlYXRtYXBFUiA8LSBlbnJpY2hIZWF0bWFwKGVucmljaFJlZ2lvbnMsIG4gPSAxMCkKcGxvdFBERihoZWF0bWFwRVIsIG5hbWUgPSAiUmVnaW9ucy1FbnJpY2gtSGVhdG1hcCIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gMTIsIEFyY2hSUHJvaiA9IHByb2osIGFkZERPQyA9IEZBTFNFKQpgYGAKIyMgTW90aWYgRW5yaWNobWVudAo8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvTW90aWZzLUVucmljaC1IZWF0bWFwLnBkZil7d2lkdGg9NDUwIGhlaWdodD02MDB9CjwvY2VudGVyPgoKIyMgUmVnaW9uIEVucmljaG1lbnQKPGJyLz48YnIvPgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL1JlZ2lvbnMtRW5yaWNoLUhlYXRtYXAucGRmKXt3aWR0aD00NTAgaGVpZ2h0PTYwMH0KPC9jZW50ZXI+CgojIENvbXB1dGluZyBjaHJvbVZBUiBEZXZpYXRpb25zIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQpVc2luZyB0aGUgcmVwcm9kdWNpYmxlIHBlYWsgc2V0IHRoYXQgd2UgZGVmaW5lZCBhYm92ZSwgd2UgY2FuIHVzZSBBcmNoUiB0byBjYWxjdWxhdGUgVEYvQW5ub3RhdGlvbiBkZXZpYXRpb25zIG9uIGEgc2luZ2xlLWNlbGwgYmFzaXMgZm9yIHRyYW5zY3JpcHRpb24gZmFjdG9ycy9hbm5vdGF0aW9ucyBpbiB0aGUgcGVha3MgaWRlbnRpZmllZCBpbiBlYWNoIGNsdXN0ZXIuIFdlIGNhbiB0aGVuIG92ZXJsYXkgdGhlc2UgZGV2aWF0aW9ucyBvbiBvbiBVTUFQIGVtYmVkZGluZy4gVGhpcyBlZmZlY3RpdmVseSBpbmZlcnMgZGlmZmVyZW5jZXMgaW4gVEYgYWN0aXZpdHkgYWNyb3NzIGFsbCBzaW5nbGUgY2VsbHMgYW5kIGlzIHZlcnkgdXNlZnVsIGluIGlkZW50aWZ5aW5nIHJlZ3VsYXRvcnkgZmFjdG9ycyBnb3Zlcm5pbmcgY2VsbCBmYXRlLgoKIyMgTW90aWYgRGV2aWF0aW9ucwpgYGB7ciBldmFsPUZBTFNFfQojQWRkIEJhY2tncm91bmQgUGVha3MgdG8gQXJjaFIgUHJvamVjdApwcm9qIDwtIGFkZEJnZFBlYWtzKHByb2opCgojQWRkIGNocm9tVkFSIERldmlhdGlvbnMgKH4yMC0yNSBtaW4gaWYgdXNpbmcgQ2lzQlAgTW90aWYgU2V0KQpwcm9qIDwtIGFkZERldmlhdGlvbnNNYXRyaXgoQXJjaFJQcm9qID0gcHJvaiwgcGVha0Fubm90YXRpb24gPSAiTW90aWYiKQoKI1Bsb3QgVmFyaWFibGUgVEZzCnBsb3RWYXJEZXYgPC0gZ2V0VmFyRGV2aWF0aW9ucyhwcm9qLCBwbG90ID0gVFJVRSkKcGxvdFBERihwbG90VmFyRGV2LCBuYW1lID0gIlBsb3QtVmFyLURldmlhdGlvbnMiLCB3aWR0aCA9IDYsIGhlaWdodCA9IDYsIEFyY2hSUHJvaiA9IHByb2osIGFkZERPQyA9IEZBTFNFKQpgYGAKCjxici8+PGJyLz4KPGNlbnRlcj4KIVtBbHRdKC4uLy4uL2ltYWdlcy9UdXRvcmlhbC9QbG90LVZhci1EZXZpYXRpb25zLnBkZil7d2lkdGg9NDUwIGhlaWdodD00NTB9CjwvY2VudGVyPgoKYGBge3IgZXZhbD1GQUxTRX0KI1RvIGFjY2VzcyBtb3RpZiBuZWVkIHRvIHNwZWNpZnkgZGV2aWF0aW9ucyx6IDogbW90aWZfbmFtZQojVHJ5IGdldEZlYXR1cmVzIHdpdGggTW90aWZNYXRyaXggdG8gc2VlIGF2YWlsYWJsZSBuYW1lcwpnZXRGZWF0dXJlcyhwcm9qLCBzZWxlY3QgPSAiUEFYNSIsIHVzZU1hdHJpeCA9ICJNb3RpZk1hdHJpeCIpCgojRGVmaW5lIHRoZSBsaXN0IG9mIG1vdGlmcyB0byBwbG90Cm1hcmtlck1vdGlmcyA8LSBjKCJHQVRBMV8zODMiLCAiQ0VCUEFfMTU1IiwgIkVCRjFfNjciLCAiSVJGNF82MzIiLCAiVEJYMjFfNzgwIiwgIlBBWDVfNzA5IikKCiNQbG90IFZpb2xpbnMgb2YgbW90aWYgZGV2aWF0aW9ucwpwbG90TGlzdCA8LSBsaXN0KCkKcGxvdExpc3RbWzFdXSA8LSBwbG90R3JvdXBzKEFyY2hSUHJvaiA9IHByb2osIAogIGdyb3VwQnkgPSAiQ2x1c3RlcnMiLCAKICBjb2xvckJ5ID0gIk1vdGlmTWF0cml4IiwgCiAgbmFtZSA9IHBhc3RlMCgiejoiLG1hcmtlck1vdGlmc1sxXSksCiAgaW1wdXRlV2VpZ2h0cyA9IGdldEltcHV0ZVdlaWdodHMocHJvaikKKQpwbG90TGlzdFtbMl1dIDwtIHBsb3RHcm91cHMoQXJjaFJQcm9qID0gcHJvaiwgCiAgZ3JvdXBCeSA9ICJDbHVzdGVycyIsIAogIGNvbG9yQnkgPSAiTW90aWZNYXRyaXgiLCAKICBuYW1lID0gcGFzdGUwKCJ6OiIsbWFya2VyTW90aWZzWzZdKSwKICBpbXB1dGVXZWlnaHRzID0gZ2V0SW1wdXRlV2VpZ2h0cyhwcm9qKQopCnBsb3RQREYocGxvdExpc3QgPSBwbG90TGlzdCwgbmFtZSA9ICJHcm91cHMtTWFya2VyLU1vdGlmRGV2aWF0aW9ucy13LUltcHV0YXRpb24iLCB3aWR0aCA9IDQsIGhlaWdodCA9IDMsICBBcmNoUlByb2ogPSBwcm9qLCBhZGRET0MgPSBGQUxTRSkKYGBgCgo8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvR3JvdXBzLU1hcmtlci1Nb3RpZkRldmlhdGlvbnMtdy1JbXB1dGF0aW9uLnBkZil7d2lkdGg9NDUwIGhlaWdodD0zNTB9CjwvY2VudGVyPgoKYGBge3IgZXZhbD1GQUxTRX0KI1Bsb3QgdGhlIFVNQVAgRW1iZWRkaW5nIHdpdGggY2hyb21WQVIgRGV2aWF0aW9ucyBPdmVybGF5ZWQKcGxvdExpc3QgPC0gbGlzdCgpCnBsb3RMaXN0W1sxXV0gPC0gcGxvdEVtYmVkZGluZyhBcmNoUlByb2ogPSBwcm9qLCBjb2xvckJ5ID0gImNvbERhdGEiLCBuYW1lID0gIkNsdXN0ZXJzIikKcGxvdExpc3RbWzJdXSA8LSBwbG90RW1iZWRkaW5nKEFyY2hSUHJvaiA9IHByb2osIGNvbG9yQnkgPSAiTW90aWZNYXRyaXgiLCBuYW1lID0gcGFzdGUwKCJ6OiIsbWFya2VyTW90aWZzKSwgaW1wdXRlV2VpZ2h0cyA9IGdldEltcHV0ZVdlaWdodHMocHJvaikpCnBsb3RQREYocGxvdExpc3QgPSBwbG90TGlzdCwgbmFtZSA9ICJVTUFQLU1hcmtlci1Nb3RpZkRldmlhdGlvbnMtdy1JbXB1dGF0aW9uIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA2LCBBcmNoUlByb2ogPSBwcm9qLCBhZGRET0MgPSBGQUxTRSkKYGBgCgo8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvVU1BUC1NYXJrZXItTW90aWZEZXZpYXRpb25zLXctSW1wdXRhdGlvbi5wZGYpe3dpZHRoPTQ1MCBoZWlnaHQ9NDUwfQo8L2NlbnRlcj4KCiMjIFJlZ2lvbiBEZXZpYXRpb25zCmBgYHtyIGV2YWw9RkFMU0V9CgojQWRkIEJhY2tncm91bmQgUGVha3MgdG8gQXJjaFIgUHJvamVjdApwcm9qIDwtIGFkZEJnZFBlYWtzKHByb2opCgojQWRkIGNocm9tVkFSIERldmlhdGlvbnMKcHJvaiA8LSBhZGREZXZpYXRpb25zTWF0cml4KEFyY2hSUHJvaiA9IHByb2osIHBlYWtBbm5vdGF0aW9uID0gIkNoSVAiKQoKI1RvIGFjY2VzcyBtb3RpZiBuZWVkIHRvIHNwZWNpZnkgZGV2aWF0aW9ucyx6IDogbW90aWZfbmFtZQojVHJ5IGdldEZlYXR1cmVzIHdpdGggTW90aWZNYXRyaXggdG8gc2VlIGF2YWlsYWJsZSBuYW1lcwpnZXRGZWF0dXJlcyhwcm9qLCBzZWxlY3QgPSAiUEFYNSIsIHVzZU1hdHJpeCA9ICJDaElQTWF0cml4IikKCiNEZWZpbmUgdGhlIGxpc3Qgb2YgcmVnaW9ucyB0byBwbG90Cm1hcmtlclJlZ2lvbnMgPC0gYygiRW5jb2RlX0s1NjJfR0FUQTEiLCAiRW5jb2RlX0dNMTI4NzhfQ0VCUEIiLCAiRW5jb2RlX0s1NjJfRWJmMSIsICJFbmNvZGVfSzU2Ml9QYXg1IikKCiNQbG90IFZpb2xpbnMgb2YgQ2hJUC1zZXEgZGV2aWF0aW9ucwpwbG90TGlzdCA8LSBsaXN0KCkKcGxvdExpc3RbWzFdXSA8LSBwbG90R3JvdXBzKEFyY2hSUHJvaiA9IHByb2osIAogIGdyb3VwQnkgPSAiQ2x1c3RlcnMiLCAKICBjb2xvckJ5ID0gIkNoSVBNYXRyaXgiLCAKICBuYW1lID0gcGFzdGUwKCJ6OiIsbWFya2VyUmVnaW9uc1sxXSksCiAgaW1wdXRlV2VpZ2h0cyA9IGdldEltcHV0ZVdlaWdodHMocHJvaikKKQpwbG90TGlzdFtbMl1dIDwtIHBsb3RHcm91cHMoQXJjaFJQcm9qID0gcHJvaiwgCiAgZ3JvdXBCeSA9ICJDbHVzdGVycyIsIAogIGNvbG9yQnkgPSAiQ2hJUE1hdHJpeCIsIAogIG5hbWUgPSBwYXN0ZTAoIno6IixtYXJrZXJSZWdpb25zWzRdKSwKICBpbXB1dGVXZWlnaHRzID0gZ2V0SW1wdXRlV2VpZ2h0cyhwcm9qKQopCnBsb3RQREYocGxvdExpc3QgPSBwbG90TGlzdCwgbmFtZSA9ICJHcm91cHMtTWFya2VyLUNoSVBEZXZpYXRpb25zLXctSW1wdXRhdGlvbiIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMywgIEFyY2hSUHJvaiA9IHByb2osIGFkZERPQyA9IEZBTFNFKQpgYGAKCjxici8+PGJyLz4KPGNlbnRlcj4KIVtBbHRdKC4uLy4uL2ltYWdlcy9UdXRvcmlhbC9Hcm91cHMtTWFya2VyLUNoSVBEZXZpYXRpb25zLXctSW1wdXRhdGlvbi5wZGYpe3dpZHRoPTQ1MCBoZWlnaHQ9MzUwfQo8L2NlbnRlcj4KCmBgYHtyIGV2YWw9RkFMU0V9CiNQbG90IHRoZSBVTUFQIEVtYmVkZGluZyB3aXRoIGNocm9tVkFSIERldmlhdGlvbnMgT3ZlcmxheWVkCnBsb3RMaXN0IDwtIGxpc3QoKQpwbG90TGlzdFtbMV1dIDwtIHBsb3RFbWJlZGRpbmcoQXJjaFJQcm9qID0gcHJvaiwgY29sb3JCeSA9ICJjb2xEYXRhIiwgbmFtZSA9ICJDbHVzdGVycyIpCnBsb3RMaXN0W1syXV0gPC0gcGxvdEVtYmVkZGluZyhBcmNoUlByb2ogPSBwcm9qLCBjb2xvckJ5ID0gIkNoSVBNYXRyaXgiLCBuYW1lID0gcGFzdGUwKCJ6OiIsbWFya2VyUmVnaW9ucyksIGltcHV0ZVdlaWdodHMgPSBnZXRJbXB1dGVXZWlnaHRzKHByb2opKQpwbG90UERGKHBsb3RMaXN0ID0gcGxvdExpc3QsIG5hbWUgPSAiVU1BUC1NYXJrZXItQ2hJUERldmlhdGlvbnMtdy1JbXB1dGF0aW9uIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA2LCBBcmNoUlByb2ogPSBwcm9qLCBhZGRET0MgPSBGQUxTRSkKYGBgCgo8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvVU1BUC1NYXJrZXItQ2hJUERldmlhdGlvbnMtdy1JbXB1dGF0aW9uLnBkZil7d2lkdGg9NDUwIGhlaWdodD00NTB9CjwvY2VudGVyPgoKIyBQZXJmb3JtaW5nIFRGIEZvb3RwcmludGluZyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KClRyYW5zY3JpcHRpb24gZmFjdG9yIGZvb3RwcmludGluZyBjYW4gYWxzbyBiZSBkb25lIGluIEFyY2hSIHdpdGggYSBzaW5nbGUgY29tbWFuZC4gV2Ugbm90ZSB0aGF0IHRoZSBmb290cHJpbnRzIGdlbmVyYXRlZCBieSB0aGUgdHV0b3JpYWwgZGF0YSBhcmUgbm90IGFzIGNsZWFuIGFzIHdvdWxkIGJlIGRlc2lyZWQgYnV0IHRoaXMgaXMgYmVjYXVzZSBvZiB0aGUgc21hbGwgc2l6ZSBvZiB0aGUgdHV0b3JpYWwgZGF0YXNldC4KCmBgYHtyIGV2YWw9RkFMU0V9CiNQbG90IE1vdGlmIEZvb3RwcmludHMgZnJvbSBwb3NpdGlvbnMgbGlzdAojUmVjb21tZW5kIGRvaW5nIGEgZmV3IG1vdGlmcyBub3QgZW50aXJlIG1vdGlmIHNldApzZUZvb3RfTm9uZSA8LSBwbG90Rm9vdHByaW50cygKICBBcmNoUlByb2ogPSBwcm9qLCAKICBwb3NpdGlvbnMgPSBnZXRQb3NpdGlvbnMocHJvailbbWFya2VyTW90aWZzXSwgCiAgZ3JvdXBCeSA9ICJDbHVzdGVycyIsCiAgbm9ybU1ldGhvZCA9ICJub25lIiwKICBwbG90TmFtZSA9ICJGb290cHJpbnRzLU5vLU5vcm1hbGl6YXRpb24iCikKYGBgCiMjIE5vIE5vcm1hbGl6YXRpb24KPGJyLz48YnIvPgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL0Zvb3RwcmludHMtTm8tTm9ybWFsaXphdGlvbi5wZGYpe3dpZHRoPTQ1MCBoZWlnaHQ9NjUwfQo8L2NlbnRlcj4KCiMjIFN1YnRyYWN0IEJpYXMKYGBge3IgZXZhbD1GQUxTRX0KI1JlLVBsb3Qgd2l0aCBkaWZmZXJlbnQgbm9ybWFsaXphdGlvbiBtZXRob2QKc2VGb290X1N1YnRyYWN0IDwtIHBsb3RGb290cHJpbnRzKAogIEFyY2hSUHJvaiA9IHByb2osIAogIGlucHV0U0UgPSBzZUZvb3RfTm9uZSwgCiAgcG9zaXRpb25zID0gZ2V0UG9zaXRpb25zKHByb2opW21hcmtlck1vdGlmc10sIAogIGdyb3VwQnkgPSAiQ2x1c3RlcnMiLAogIG5vcm1NZXRob2QgPSAic3VidHJhY3QiLAogIHBsb3ROYW1lID0gIkZvb3RwcmludHMtU3VidHJhY3QtQmlhcyIKKQpgYGAKPGJyLz48YnIvPgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL0Zvb3RwcmludHMtU3VidHJhY3QtQmlhcy5wZGYpe3dpZHRoPTQ1MCBoZWlnaHQ9NjUwfQo8L2NlbnRlcj4KCiMjIERpdmlkZSBCaWFzCmBgYHtyIGV2YWw9RkFMU0V9CiNSZS1QbG90IHdpdGggZGlmZmVyZW50IG5vcm1hbGl6YXRpb24gbWV0aG9kCnNlRm9vdF9EaXZpZGUgPC0gcGxvdEZvb3RwcmludHMoCiAgQXJjaFJQcm9qID0gcHJvaiwgCiAgaW5wdXRTRSA9IHNlRm9vdF9Ob25lLCAKICBwb3NpdGlvbnMgPSBnZXRQb3NpdGlvbnMocHJvailbbWFya2VyTW90aWZzXSwgCiAgZ3JvdXBCeSA9ICJDbHVzdGVycyIsCiAgbm9ybU1ldGhvZCA9ICJkaXZpZGUiLAogIHBsb3ROYW1lID0gIkZvb3RwcmludHMtRGl2aWRlLUJpYXMiCikKYGBgCjxici8+PGJyLz4KPGNlbnRlcj4KIVtBbHRdKC4uLy4uL2ltYWdlcy9UdXRvcmlhbC9Gb290cHJpbnRzLURpdmlkZS1CaWFzLnBkZil7d2lkdGg9NDUwIGhlaWdodD02NTB9CjwvY2VudGVyPgoKIyMgVFNTIEVucmljaG1lbnQKYGBge3IgZXZhbD1GQUxTRX0KCiNBZGQgQ292ZXJhZ2VzIGZvciBTYW1wbGVzIHByaW9yIHRvIGZvb3RwcmludApwcm9qIDwtIGFkZEdyb3VwQ292ZXJhZ2VzKEFyY2hSUHJvaiA9IHByb2osIGdyb3VwQnkgPSAiU2FtcGxlIikKCiNUU1MgYnkgc2FtcGxlClRTU19TYW1wbGVzIDwtIHBsb3RGb290cHJpbnRzKAogIEFyY2hSUHJvaiA9IHByb2osIAogIHBvc2l0aW9ucyA9IEdSYW5nZXNMaXN0KFRTUyA9IGdldFRTUyhwcm9qKSksIAogIGdyb3VwQnkgPSAiU2FtcGxlIiwKICBub3JtTWV0aG9kID0gIm5vbmUiLAogIHBsb3ROYW1lID0gIlRTU19TYW1wbGVzIiwKICBmbGFuayA9IDIwMDAsCiAgZmxhbmtOb3JtID0gMTAwCikKYGBgCjxici8+PGJyLz4KPGNlbnRlcj4KIVtBbHRdKC4uLy4uL2ltYWdlcy9UdXRvcmlhbC9UU1NfU2FtcGxlcy5wZGYpe3dpZHRoPTQ1MCBoZWlnaHQ9NjUwfQo8L2NlbnRlcj4KCmBgYHtyIGV2YWw9RkFMU0V9CgojVFNTIGJ5IGNsdXN0ZXJzClRTU19DbHVzdGVycyA8LSBwbG90Rm9vdHByaW50cygKICBBcmNoUlByb2ogPSBwcm9qLCAKICBwb3NpdGlvbnMgPSBHUmFuZ2VzTGlzdChUU1MgPSBnZXRUU1MocHJvaikpLCAKICBncm91cEJ5ID0gIkNsdXN0ZXJzIiwKICBub3JtTWV0aG9kID0gIm5vbmUiLAogIHBsb3ROYW1lID0gIlRTU19DbHVzdGVycyIsCiAgZmxhbmsgPSAyMDAwLAogIGZsYW5rTm9ybSA9IDEwMAopCmBgYAo8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvVFNTX0NsdXN0ZXJzLnBkZil7d2lkdGg9NDUwIGhlaWdodD02NTB9CjwvY2VudGVyPgoKIyBBbmFseXplIFRyYWplY3RvcmllcyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCiMjIE15ZWxvaWQgVHJhamVjdG9yeQpgYGB7ciBldmFsPUZBTFNFfQojRmlyc3Qgd2UgbmVlZCB0byBjcmVhdGUgYSBUcmFqZWN0b3J5IGFuZCBhZGQgaXQgdG8gQXJjaFJQcm9qIGNlbGxDb2xEYXRhCnByb2ogPC0gYWRkVHJhamVjdG9yeShBcmNoUlByb2ogPSBwcm9qLCBuYW1lID0gIk15ZWxvaWQiLCB0cmFqZWN0b3J5ID0gYyhwYXN0ZTAoIkNsdXN0ZXIiLCBjKDcsMiwzLDQsNSkpKSkKCiNBZGRpdGlvbmFsbHkgd2UgY2FuIHBsb3QgdGhlc2UgZmVhdHVyZXMgb24gdG9wIG9mIHRoZSBVTUFQIGVtYmVkZGluZwpwbG90TGlzdCA8LSBsaXN0KCkKcGxvdExpc3RbWzFdXSA8LSBwbG90RW1iZWRkaW5nKEFyY2hSUHJvaiA9IHByb2osIGNvbG9yQnkgPSAiY29sRGF0YSIsIG5hbWUgPSAiQ2x1c3RlcnMiLCBwbG90UGFyYW1zID0gbGlzdChsYWJlbE1lYW5zPVRSVUUpKQpwbG90TGlzdFtbMl1dIDwtIHBsb3RUcmFqZWN0b3J5KHByb2osIHRyYWplY3RvcnkgPSAiTXllbG9pZCIsIGNvbG9yQnkgPSAiY29sRGF0YSIsIG5hbWUgPSAiTXllbG9pZCIpCnBsb3RMaXN0W1szXV0gPC0gcGxvdFRyYWplY3RvcnkocHJvaiwgdHJhamVjdG9yeSA9ICJNeWVsb2lkIiwgY29sb3JCeSA9ICJHZW5lU2NvcmVNYXRyaXgiLCBuYW1lID0gIkNFQlBCIikKcGxvdExpc3RbWzRdXSA8LSBwbG90VHJhamVjdG9yeShwcm9qLCB0cmFqZWN0b3J5ID0gIk15ZWxvaWQiLCBjb2xvckJ5ID0gIk1vdGlmTWF0cml4IiwgbmFtZSA9ICJ6OkNFQlBCXzE0MCIpCnBsb3RQREYocGxvdExpc3QgPSBwbG90TGlzdCwgbmFtZSA9ICJQbG90LVVNQVAtTXllbG9pZC1UcmFqZWN0b3J5Iiwgd2lkdGggPSA2LCBoZWlnaHQgPSA2LCBBcmNoUlByb2ogPSBwcm9qLCBhZGRET0MgPSBGQUxTRSkKYGBgCjxici8+PGJyLz4KPGNlbnRlcj4KIVtBbHRdKC4uLy4uL2ltYWdlcy9UdXRvcmlhbC9QbG90LVVNQVAtTXllbG9pZC1UcmFqZWN0b3J5LnBkZil7d2lkdGg9NDUwIGhlaWdodD02NTB9CjwvY2VudGVyPgoKYGBge3IgZXZhbD1GQUxTRX0KI05leHQgd2UgY2FuIGFjY2VzcyB2YXJpYWJsZSBmZWF0dXJlcyBhY3Jvc3MgdGhlIHRyYWplY3RvcnkgYW5kIHN1bW1hcml6ZQpUcmFqTXllbG9pZE1NIDwtIGdldFRyYWplY3RvcnkoQXJjaFJQcm9qID0gcHJvaiwgbmFtZSA9ICJNeWVsb2lkIiwgdXNlTWF0cml4ID0gIk1vdGlmTWF0cml4IiwgbG9nMk5vcm0gPSBGQUxTRSkKVHJhak15ZWxvaWRHUyA8LSBnZXRUcmFqZWN0b3J5KEFyY2hSUHJvaiA9IHByb2osIG5hbWUgPSAiTXllbG9pZCIsIHVzZU1hdHJpeCA9ICJHZW5lU2NvcmVNYXRyaXgiKQoKI1dlIGNhbiB0aGVuIHBsb3QgYSBoZWF0bWFwIGZvciB0aGlzIHRyYWplY3RvcnkgdG8gc2VlIHZhcmlhYmxlIGZlYXR1cmVzCnBsb3RMaXN0IDwtIGxpc3QoKQpwbG90TGlzdFtbMV1dIDwtIHRyYWplY3RvcnlIZWF0bWFwKFRyYWpNeWVsb2lkTU0pCnBsb3RMaXN0W1syXV0gPC0gdHJhamVjdG9yeUhlYXRtYXAoVHJhak15ZWxvaWRHUykKcGxvdFBERihwbG90TGlzdCA9IHBsb3RMaXN0LCBuYW1lID0gIk15ZWxvaWQtVHJhamVjdG9yeS1IZWF0bWFwIiwgd2lkdGggPSA4LCBoZWlnaHQgPSAxMiwgQXJjaFJQcm9qID0gcHJvaiwgYWRkRE9DID0gRkFMU0UpCmBgYAo8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvVHV0b3JpYWwvTXllbG9pZC1UcmFqZWN0b3J5LUhlYXRtYXAucGRmKXt3aWR0aD00NTAgaGVpZ2h0PTY1MH0KPC9jZW50ZXI+CgojIyBMeW1waG9pZCBUcmFqZWN0b3J5CmBgYHtyIGV2YWw9RkFMU0V9CiNGaXJzdCB3ZSBuZWVkIHRvIGNyZWF0ZSBhIFRyYWplY3RvcnkgYW5kIGFkZCBpdCB0byBBcmNoUlByb2ogY2VsbENvbERhdGEKcHJvaiA8LSBhZGRUcmFqZWN0b3J5KEFyY2hSUHJvaiA9IHByb2osIG5hbWUgPSAiTHltcGhvaWQiLCB0cmFqZWN0b3J5ID0gYyhwYXN0ZTAoIkNsdXN0ZXIiLCBjKDcsOCw5LDEwKSkpKQoKI0FkZGl0aW9uYWxseSB3ZSBjYW4gcGxvdCB0aGVzZSBmZWF0dXJlcyBvbiB0b3Agb2YgdGhlIFVNQVAgZW1iZWRkaW5nCnBsb3RMaXN0IDwtIGxpc3QoKQpwbG90TGlzdFtbMV1dIDwtIHBsb3RFbWJlZGRpbmcoQXJjaFJQcm9qID0gcHJvaiwgY29sb3JCeSA9ICJjb2xEYXRhIiwgbmFtZSA9ICJDbHVzdGVycyIsIHBsb3RQYXJhbXMgPSBsaXN0KGxhYmVsTWVhbnM9VFJVRSkpCnBsb3RMaXN0W1syXV0gPC0gcGxvdFRyYWplY3RvcnkocHJvaiwgdHJhamVjdG9yeSA9ICJMeW1waG9pZCIsIGNvbG9yQnkgPSAiY29sRGF0YSIsIG5hbWUgPSAiTHltcGhvaWQiKQpwbG90TGlzdFtbM11dIDwtIHBsb3RUcmFqZWN0b3J5KHByb2osIHRyYWplY3RvcnkgPSAiTHltcGhvaWQiLCBjb2xvckJ5ID0gIkdlbmVTY29yZU1hdHJpeCIsIG5hbWUgPSAiUEFYNSIpCnBsb3RMaXN0W1s0XV0gPC0gcGxvdFRyYWplY3RvcnkocHJvaiwgdHJhamVjdG9yeSA9ICJMeW1waG9pZCIsIGNvbG9yQnkgPSAiTW90aWZNYXRyaXgiLCBuYW1lID0gIno6UEFYNV83MDkiKQpwbG90UERGKHBsb3RMaXN0ID0gcGxvdExpc3QsIG5hbWUgPSAiUGxvdC1VTUFQLUx5bXBob2lkLVRyYWplY3RvcnkiLCB3aWR0aCA9IDYsIGhlaWdodCA9IDYsIEFyY2hSUHJvaiA9IHByb2osIGFkZERPQyA9IEZBTFNFKQpgYGAKPGJyLz48YnIvPgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL1Bsb3QtVU1BUC1MeW1waG9pZC1UcmFqZWN0b3J5LnBkZil7d2lkdGg9NDUwIGhlaWdodD02NTB9CjwvY2VudGVyPgoKYGBge3IgZXZhbD1GQUxTRX0KI05leHQgd2UgY2FuIGFjY2VzcyB2YXJpYWJsZSBmZWF0dXJlcyBhY3Jvc3MgdGhlIHRyYWplY3RvcnkgYW5kIHN1bW1hcml6ZQpUcmFqTHltcGhvaWRNTSA8LSBnZXRUcmFqZWN0b3J5KEFyY2hSUHJvaiA9IHByb2osIG5hbWUgPSAiTHltcGhvaWQiLCB1c2VNYXRyaXggPSAiTW90aWZNYXRyaXgiLCBsb2cyTm9ybSA9IEZBTFNFKQpUcmFqTHltcGhvaWRHUyA8LSBnZXRUcmFqZWN0b3J5KEFyY2hSUHJvaiA9IHByb2osIG5hbWUgPSAiTHltcGhvaWQiLCB1c2VNYXRyaXggPSAiR2VuZVNjb3JlTWF0cml4IikKCiNXZSBjYW4gdGhlbiBwbG90IGEgaGVhdG1hcCBmb3IgdGhpcyB0cmFqZWN0b3J5IHRvIHNlZSB2YXJpYWJsZSBmZWF0dXJlcwpwbG90TGlzdCA8LSBsaXN0KCkKcGxvdExpc3RbWzFdXSA8LSB0cmFqZWN0b3J5SGVhdG1hcChUcmFqTHltcGhvaWRNTSwgbGFiZWxNYXJrZXJzID0gIlBBWDVfNzA5IikKcGxvdExpc3RbWzJdXSA8LSB0cmFqZWN0b3J5SGVhdG1hcChUcmFqTHltcGhvaWRHUykKcGxvdFBERihwbG90TGlzdCA9IHBsb3RMaXN0LCBuYW1lID0gIkx5bXBob2lkLVRyYWplY3RvcnktSGVhdG1hcCIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gMTIsIEFyY2hSUHJvaiA9IHByb2osIGFkZERPQyA9IEZBTFNFKQpgYGAKPGJyLz48YnIvPgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL1R1dG9yaWFsL0x5bXBob2lkLVRyYWplY3RvcnktSGVhdG1hcC5wZGYpe3dpZHRoPTQ1MCBoZWlnaHQ9NjUwfQo8L2NlbnRlcj4KCiMgQ2l0YXRpb24KCiMgUmVmZXJlbmNlcyAKMS4gCjIuIAozLiAKNC4KNS4KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo=